phlib / console-process
控制台实现。
Requires
- php: ^8.0
- ext-pcntl: *
- ext-posix: *
- symfony/console: ^5 || ^6
Requires (Dev)
README
使用PHP的进程控制函数实现的控制台信号实现。
有2种实现。
- 后台命令。重复执行命令,直到使用信号处理器中断。
- 守护进程命令。在后台命令的基础上允许进程分离(分离)。
安装
通过Composer
$ composer require phlib/console-process
后台命令
基本用法
后台命令的实现方式与您所习惯的常规Symfony Command相同,但是它必须允许多次调用execute()
方法。每次执行之间有一个处理延迟,可以自定义。
<?php declare(strict_types=1); use Phlib\Console\Command\BackgroundCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class MyProcessCommand extends BackgroundCommand { protected function configure(): void { $this->setName('my:process') ->setDescription('My background process.'); } protected function execute(InputInterface $input, OutputInterface $output): int { $output->writeln('Doing important work!'); return 0; } }
停止执行
正常使用
通常,命令将继续执行,直到被信号中断,例如用户按下Ctrl+C
。
自终止
或者,如果实现具有有限的任务,例如批量删除记录,它可能需要在任务完成时自行终止。这可以通过调用shutdown()
来完成。
class MyProcessCommand extends BackgroundCommand { // ... protected function execute(InputInterface $input, OutputInterface $output): int { $countDeleted = $this->deleteBatchOfRecords(); if ($countDeleted === 0) { $output->writeln('All done!'); $this->shutdown(); } return 0; } }
非零退出码
如果执行返回非零退出码,迭代将停止,并将退出码传递回控制台,就像常规的Symfony Command一样。
class MyProcessCommand extends BackgroundCommand { // ... protected function execute(InputInterface $input, OutputInterface $output): int { $isInputValid = $this->someValidationChecks($input); if ($isInputValid === false) { $output->writeln('Message explaining invalid input'); return 1; } // do some work return 0; } }
生命周期方法
后台命令在进程开始和结束时还有额外的调用方法。这对于任何初始化或最终清理非常有用。
onStart(InputInterface $input, OutputInterface $output): void
- 类似于标准的
initialize()
;对于DaemonCommand
很有用。
- 类似于标准的
onShutdown(InputInterface $input, OutputInterface $output): void
onException(\Exception $e, InputInterface $input, OutputInterface $output): void
class MyProcessCommand extends BackgroundCommand { // ... protected function onShutdown(InputInterface $input, OutputInterface $output): void { $output->writeln('onShutdown method called.'); } }
守护进程命令
基本用法
除了扩展不同的类之外,守护进程命令的外观和功能与后台命令类似。PID文件参数是可选的。如果没有指定,进程将根据命令名称生成自己的PID文件。
<?php declare(strict_types=1); use Phlib\Console\Command\DaemonCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class MyProcessCommand extends DaemonCommand { protected function configure() { $this->setName('my:process') ->setDescription('My background process.'); } protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln('Doing important work!'); } }
输出
一旦守护进程分离,原始输出也会丢失。可以使用--child-log | -o
选项指定写入输出的文件名。或者,可以覆盖createChildOutput()
方法以返回新的输出实例。例如
use Symfony\Component\Console\Output\StreamOutput; class MyProcessCommand extends DaemonCommand { // ... protected function createChildOutput() { return new MyOutputToLoggerClass(); } }
生命周期方法
守护进程命令有额外的标准Symfony命令方法和后台命令方法,在进程生命周期期间被调用。以下示例展示了方法的重写。
class MyProcessCommand extends DaemonCommand { // ... protected function onBeforeDaemonize(InputInterface $input, OutputInterface $output) { $output->writeln('onBeforeDaemonize method called.'); } protected function onAfterDaemonizeChild(InputInterface $input, OutputInterface $output) { $output->writeln('onAfterDaemonizeChild method called.'); } protected function onAfterDaemonizeParent(InputInterface $input, OutputInterface $output) { $output->writeln('onAfterDaemonizeParent method called.'); } protected function onStart(InputInterface $input, OutputInterface $output): void { // Similar to `onAfterDaemonizeChild()` but also called if `--daemonize` option is not set. $output->writeln('onStart method called.'); } }
命令行
# path/to/my/process start -d
# path/to/my/process status
# path/to/my/process stop
选项
许可协议
本软件包是免费软件:您可以在GNU Lesser General Public License的条款下重新分发和/或修改它,该协议由Free Software Foundation发布,无论是第3版还是(根据您的选择)任何后续版本。
本程序旨在供您使用,但没有任何保证;甚至没有关于其适销性或适用于特定目的的暗示保证。有关详细信息,请参阅GNU Lesser General Public License。
您应该已收到GNU Lesser General Public License的副本。如果没有,请参阅https://gnu.ac.cn/licenses/。