phlib/console-process

4.0.0 2023-10-14 06:44 UTC

This package is auto-updated.

Last update: 2024-08-31 00:29:30 UTC


README

Code Checks Codecov Latest Stable Version Total Downloads Licence

使用PHP的进程控制函数实现的控制台信号实现。

有2种实现。

  1. 后台命令。重复执行命令,直到使用信号处理器中断。
  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/