5

I've created a console command for my symfony2 project and I want to execute it from a controller without blocking the controller output (in background).

Normally is executed like this:

$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);

But running like this the user will have to wait for the task to be finished which can take several minutes.

A solution is:

$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();

No errors given, the controller renders the output, but the task is not executed.

Another solution is:

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

found here Symfony2 - process launching a symfony2 command but doesn't work on my example.

Community
  • 1
  • 1
Ceparu Stefan
  • 327
  • 2
  • 4
  • 13
  • Is `console` in `./app` subdirectory, or in `./bin` subdirectory (newer symfony versions) - if it is in `bin`, then you need to update path to console command. Also, what does `$process->isSuccessful()` returns after `run()` ? – Miro May 11 '16 at 21:08
  • also, does the tas krun successfully if you run `nohup php PATH/console update:stock --env=ENV > /dev/null 2>&1 &` in shell command line ? – Miro May 11 '16 at 21:16
  • The console is in app folder(I use symfony v2.8). The command runs ok in putty, but there is a catch, if I press any key after I run the command it will kill the process ... I think that's the problem, because I've put a text file for the output(instead of /dev/null) and it shows the output from the controller which is a json response. – Ceparu Stefan May 12 '16 at 00:12
  • hmm i don't understand, if you run the command in putty, it should start the command and run it in the background and you should get immediately shell (putty) command prompt. you are saying, that if you press any key,while in command prompt that it stops command running in background ? – Miro May 12 '16 at 00:19
  • Miro, yes that's correct. It's strange for me too. You can test it to see for yourself. – Ceparu Stefan May 12 '16 at 15:10
  • so how do you know (in command line), that the process has stopped ? if the output is redirected to /dev/null you have no way to tell the process stopped ? are you sure the command runs correctly (try to run it without nohup on foregruond without output redirection) – Miro May 12 '16 at 15:15
  • Ok, I've make a test and it seams everything is ok. The command is running and on finish it shows [1]+ Done nohup php app/console update:stock --env=dev > /dev/null 2>&1 But the problem remains when I start a process with this command ... seams that the answer below explains why the process is killed – Ceparu Stefan May 12 '16 at 15:22
  • @CeparuStefan could you fix this issue ? I am having same issue. I donot want to used RabbitMQ – user1687891 May 16 '21 at 08:15

3 Answers3

2

Processes hierarchical

All processes in system have own hierarchical.

As example: we have a Process A, after the launch of which we run Process B. If you kill Process A, then the Process B killed to, because Process B is child of Process A.

You problem

The each request (http) Apache create a new child process for run PHP code and return stdoutput to client (Logic of Nginx + PHPFPM - same). And after create child process (via Symfony/Process library), this process is child of apache or fpm process. After complete request (return response to apache or nginx), the server kill child process (where executed PHP code).

Solutions for you:

  1. Good idea for runs background commands - use nohup (tutorial)
  2. The vary good idea for any applications - use AMQP protocol between processes. (tutorial via RabbitMQ)

P.S.

In my projects, for runs background tasks, i use RabbitMQ.

ZhukV
  • 2,892
  • 6
  • 25
  • 36
  • For the first solution. I've started the Process B and the command I'm running is using nohup, but if the process B is killed it doesn't matter if I use nohup or not, right? – Ceparu Stefan May 12 '16 at 15:14
  • @CeparuStefan, sorry, i do not know, because i not use nohup in my projects. I use only AMQP protocol for between processes. – ZhukV May 12 '16 at 18:14
0

Let me extend @CerapuStefan 's solution

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

nohup is important

olidem
  • 1,961
  • 2
  • 20
  • 45
0

you can set output to new NullOutput.

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

But the best thing is to use RabbitMqueue

Houssein Zouari
  • 712
  • 6
  • 18