Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/235.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 中止和恢复Symfony控制台命令_Php_Symfony_Console - Fatal编程技术网

Php 中止和恢复Symfony控制台命令

Php 中止和恢复Symfony控制台命令,php,symfony,console,Php,Symfony,Console,我有一个Symfony Console命令,它迭代一个潜在的大型项目集合,并对每个项目执行一项任务。由于集合可能很大,因此该命令可能需要很长时间才能运行(小时)。命令完成后,将显示一些统计信息 我希望能够以一种好的方式中止该命令。现在,如果我中止它(即在CLI中使用ctrl+c),则没有统计信息摘要,也无法输出恢复命令所需的参数。另一个问题是,命令可能在处理一个项目的过程中被终止——如果它只能在处理项之间终止,那就更好了。 那么,有没有一种方法可以告诉命令“尽快很好地中止”,或者将ctrl+c命

我有一个
Symfony Console
命令,它迭代一个潜在的大型项目集合,并对每个项目执行一项任务。由于集合可能很大,因此该命令可能需要很长时间才能运行(小时)。命令完成后,将显示一些统计信息

我希望能够以一种好的方式中止该命令。现在,如果我中止它(即在CLI中使用ctrl+c),则没有统计信息摘要,也无法输出恢复命令所需的参数。另一个问题是,命令可能在处理一个项目的过程中被终止——如果它只能在处理项之间终止,那就更好了。 那么,有没有一种方法可以告诉命令“尽快很好地中止”,或者将ctrl+c命令解释为这样

我试着使用
ConsoleEvents::TERMINATE
事件,尽管此事件的处理程序仅在命令完成时启动,而不是在我按住ctrl+c键时启动。我还没能找到关于发出这种可恢复命令的更多信息。

你应该看看的是,谷歌的信号处理。它的
execute
方法只是通过
pcntl\u signal()
函数调用链接一些回调。一个常见的情况应该是这样的:

<?php
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand as Command;

class YourCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        pcntl_signal(SIGTERM, array(&$this, 'stopCommand', $output));
        pcntl_signal(SIGINT, array(&$this, 'stopCommand', $output));
        pcntl_signal(SIGHUP, array(&$this, 'restartCommand', $output));

        // The real execute method body
    }

    public function stopCommand(OutputInterface $output)
    {
        $output->writeln('Stopping');

        // Do what you need to stop your process
    }

    public function restartCommand(OutputInterface $output)
    {
        $output->writeln('Restarting');

        // Do what you need to restart your process
    }
}

这对我来说很有用。在实际执行信号处理程序之前,需要调用
pcntl\u signal\u dispatch
。没有它,所有任务都将首先完成

<?php
use Symfony\Component\Console\Command\Command;

class YourCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        pcntl_signal(SIGTERM, [$this, 'stopCommand']);
        pcntl_signal(SIGINT, [$this, 'stopCommand']);

        $this->shouldStop = false;

        foreach ( $this->tasks as $task )
        {
            pcntl_signal_dispatch();
            if ( $this->shouldStop ) break; 
            $task->execute();
        }

        $this->showSomeStats($output);
    }

    public function stopCommand()
    {
        $this->shouldStop = true;
    }
}

答案比需要的更复杂。当然,您可以注册POSIX信号处理程序,但是如果只需要处理基本中断之类的信号,那么您应该在命令上定义析构函数


class YourCommand extends Command
{
    // Other code goes here.

    __destruct()
    {
        $this->shouldStop = true;
    }
}
您希望注册POSIX信号的情况是针对
SIGCONT
信号,它可以处理已停止进程的恢复(
SIGSTOP

另一种情况是,您希望每个信号的行为都不同;然而,在大多数情况下,
SIGINT
SIGTERM
以及少数其他人将使用相同的“OMG进程已终止”操作注册

除了这些示例之外,不需要注册信号事件。这就是析构函数存在的原因


您甚至可以使用
\uu destruct
方法扩展Symfony的base
命令
类,该方法将自动为每个命令提供清理功能;如果一个特定的命令需要额外的操作,只需覆盖它。

我认为通过将您的
输入作为交互式输入,您将能够解决这个问题,但我不知道您应该如何准确地实现它,以便在特定的按键时终止该命令,并提供此链接可能有帮助的统计信息[逐步创建交互式命令或您可以在命令中检查事件侦听器,并根据该命令终止您的命令[非常感谢,这和上面的评论让我找到了解决方案。您的示例缺少对pcntl_signal_dispatch的调用,并且还有一个语法错误:回调数组只有两个元素。您不能在这些元素之后插入参数。@JeroenDeDauw,哦,这是一些伪代码,我的错:)这就是我要找的,谢谢,但有一个提示:您我们需要设置declare(ticks=1);谢谢,由于PHP7.1,您还可以通过执行
pcntl\u async\u signals(true);
@createproblem如果在循环中使用
pcntl\u signal\u dispatch()
pcntl\u async\u signals(true)
,则不需要
declare(ticks=1)