Symfony2 запускает консольную команду в фоновом режиме

Я создал консольную команду для своего проекта 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 - процесс запуска команды symfony2,но не работает на моем примере.

3 ответа

Процессы иерархические

Все процессы в системе имеют собственную иерархию.

Как пример: у нас есть Process A, после запуска которого мы запускаем Process B, Если ты убьешь Process Aтогда Process B убит, потому что Process B это ребенок Process A,

Вы проблема

Каждый запрос (http) Apache создает новый дочерний процесс для запуска PHP-кода и возвращает stdoutput клиенту (логика Nginx + PHPFPM - то же самое). И после создания дочернего процесса (через Symfony/Process library), этот процесс является дочерним процессом apache или fpm. После завершения запроса (ответ на apache или nginx) сервер уничтожает дочерний процесс (где исполняется код PHP).

Решения для вас:

  1. Хорошая идея для запуска фоновых команд - используйте nohup ( учебник)
  2. Отличная идея для любых приложений - использовать протокол AMQP между процессами. ( учебник через RabbitMQ)

PS

В моих проектах для выполнения фоновых задач я использую RabbitMQ.

Вы можете установить выход на новый NullOutput.

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

Но лучше всего использовать RabbitMqueue

Позвольте мне расширить решение @CerapuStefan

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

nohup это важно

Другие вопросы по тегам