Symfony2在后台运行控制台命令

时间:2016-05-11 20:10:55

标签: symfony background-process symfony-process

我已经为我的symfony2项目创建了一个控制台命令,我想从控制器执行它而不阻塞控制器输出(在后台)。

通常执行方式如下:

$application = new Application($kernel);
$application->setAutoExit(true);

// AppBundle/Command/UpdateStockCommand.php
      $input = new ArrayInput(array(
          'command' => 'update:stock',
        ));

$output = new NullOutput();
$application->run($input, $output);

但是像这样运行,用户必须等待完成任务,这可能需要几分钟。

解决方案是:

$kernel = $this->get('kernel');
$process = new \Symfony\Component\Process\Process('nohup php '. $kernel->getRootDir() .'/console update:stock --env='. $kernel->getEnvironment() .' > /dev/null 2>&1 &');
//$process->start();
$process->run();

没有给出错误,控制器会渲染输出,但不会执行任务。

另一种解决方案是:

exec('/usr/bin/php '.$this->get('kernel')->getRootDir().'/console update:stock --env=dev > /dev/null 2>&1 &');

在此处找到Symfony2 - process launching a symfony2 command 但不适用于我的示例。

3 个答案:

答案 0 :(得分:2)

处理分层

系统中的所有进程都有自己的层次结构。

例如:我们有一个Process A,在我们运行Process B之后。如果你杀了Process A,那么Process B被杀,因为Process BProcess A的孩子。

你有问题

每个请求(http)Apache为运行PHP代码创建一个新的子进程并将stdoutput返回给客户端(Nginx + PHPFPM的逻辑 - 相同)。在创建子进程(通过Symfony/Process library)之后,此进程是apache或fpm进程的子进程。完成请求(返回对apache或nginx的响应)后,服务器终止子进程(执行PHP代码)。

为您解决方案:

  1. 运行后台命令的好主意 - 使用nohuptutorial
  2. 任何应用程序的好主意 - 在进程之间使用AMQP协议。 (tutorial via RabbitMQ
  3. P.S。

    在我的项目中,对于运行后台任务,我使用RabbitMQ。

答案 1 :(得分:1)

您可以将输出设置为新的NullOutput。

   $output = new NullOutput();
   $application->run($input, $output);

但是最好的方法是使用RabbitMqueue

答案 2 :(得分:0)

让我扩展@CerapuStefan的解决方案

exec('bash -c "exec nohup setsid '.$this->get('kernel')->getRootDir().'/console update:stock --env=dev > /dev/null 2>&1 &"');

nohup很重要

相关问题