facile-it/terminable-loop-command

一个Shell+PHP包装器,用于在守护进程或Kubernetes下循环运行Symfony控制台命令

1.2.2 2024-03-17 21:20 UTC

This package is auto-updated.

Last update: 2024-09-19 00:03:17 UTC


README

Latest Stable Version Latest Unstable Version Build status Coverage status

一个Shell+PHP组合,用于在守护进程或Kubernetes下循环运行Symfony控制台命令,而不是使用长时间运行的过程。

此软件包包含一个 shell 脚本 和一个 抽象的Symfony控制台命令类;您需要编写扩展该类的命令,并通过shell脚本启动它。理想情况下,脚本应作为容器入口点使用,或与Docker Compose、Kubernetes、supervisord等一起启动。

安装

composer require facile-it/terminable-loop-command

使用方法

将所需执行的PHP脚本附加到shell脚本中,以循环启动

vendor/bin/terminable-loop-command.sh my_custom_command.php

... 其中 my_custom_command.php 启动您的命令类,该类必须扩展 AbstractTerminableCommand (见此存储库中的测试存根

使用常见Symfony应用的命令示例

在使用它时,请记住将 bin/console 作为第一个参数调用

vendor/bin/terminable-loop-command.sh bin/console my:command --optionA

... 其中命令类似于以下内容

<?php

namespace Acme\Command;

use Facile\TerminableLoop\AbstractTerminableCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MyCommand extends AbstractTerminableCommand
{
    public function __construct()
    {
        parent::__construct('my:command');
    }

    protected function commandBody(InputInterface $input, OutputInterface $output): int
    {
        $this->setSleepDuration(60);

        // do something
        
        if (! $this->shouldSleep()) {
            // you can customize sleep duration during execution, even conditionally
            $this->setSleepDuration(0); 
        }

        return 0;
    }
}

为什么?

当运行PHP应用时,您可能会遇到需要持续运行的 后台命令。您可以尝试将其编写为长时间运行的过程,但它可能导致内存泄漏和其他问题。

使用这个小巧的Shell+PHP组合,您可以有一个简单的循环,

  • 启动命令
  • 执行某些操作
  • 暂停指定的时间
  • 关闭并重新启动

shell脚本拦截SIGTERM/SIGINT信号,因此当接收到这些信号时,PHP脚本将立即停止,但停止是优雅的,因为命令体的执行永远不会被截断。

这意味着您可以轻松获得 没有内存问题运行的PHP守护进程脚本;如果您在Kubernetes环境中运行此脚本,这将非常有用,因为编排器将负责运行脚本,同时它将在发生崩溃时应用适当的 重启策略。最后但并非最不重要的是,信号处理将与关闭请求很好地配合,例如在推出新部署期间。

工作原理

shell脚本非常基本,它会循环调用所需的命令,直到以不同的退出代码退出;它还会拦截SIGTERM/SIGKILL信号并将它们转发给PHP进程。

PHP命令设计为首先执行主任务(AbstractTerminableCommand::commandBody()函数),然后暂停指定的时间,这可以在命令执行期间随时自定义;这很强大,因为您可以让命令逻辑决定两次命令执行之间的等待时间,甚至什么也不等待。

PHP类还优雅地处理信号,这意味着如果信号在commandBody()函数期间接收,它将等待其完成;如果在睡眠阶段接收,它将立即终止它。如果由于信号终止,命令将以退出代码143退出,这意味着我们是因为信号而退出的:这将中断shell脚本循环的执行,而不会被监督代理,如Kubernetes视为错误。