Executing a sub-process from PHP is a nightmare... of course, only if you want to get it right. There are so many things that can go wrong, and PHP itself does not help as it has many quirks depending on the platform you are using. That's why I created the Process component some years ago. And since then, many developers helped us enhancing and fixing the code to get it right.
For Symfony 2.2, we have made several improvements.
Contributed by
Romain Neutron
in #5731.
Getting incremental Output from a Process¶
Instead of using run()
to execute a process, you can start()
it:run()
is blocking and waits for the process to finish, start()
creates
a background process. One way to get feedback from a running command is to
pass a callback when starting/running the process:
1 2 3 4 5 6 7 8 9 10 11 12 | useSymfony\Component\Process\Process;$process=newProcess('ls -lsa');// the same works when using start instead of run$process->run(function($type,$data){if(Process::ERR==$type){// $data was sent to the error output}else{// $data was sent to the standard output}}); |
But sometimes, using a callback is not possible. As of Symfony 2.2, you can
still get the incremental output data by using the getIncrementalOutput()
and getIncrementalErrorOutput()
methods; they return the new outputs since
the last call whereas getOutput()
and getErrorOutput()
return the
complete outputs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | useSymfony\Component\Process\Process;$processes=array();$processes[]=newProcess('ls -lsa');$processes[]=newProcess('ps waux');while(count($processes)>0){foreach($processesas$i=>$process){if(!$process->isStarted()){echo"Process starts\n";$process->start();continue;}echo$process->getIncrementalOutput();echo$process->getIncrementalErrorOutput();if(!$process->isRunning()){echo"Process stopped\n";unset($processes[$i]);}}sleep(1);} |
Restarting a Process¶
In the previous example, you might want to restart one of the processes if it crashes; you can now possible:
1 2 3 4 5 6 7 8 9 | useSymfony\Component\Process\ProcessBuilder;if(!$process->isRunning()){if(!$process->isSuccessful()){$cloned=$process->restart();// ...}} |
Getting the Status of a running Process¶
When you run a set of processes, you might want to restart processes that died (like in the previous example). But when a process is not even able to start, there is no point in restarting it. As of 2.2, you can check the status of a process and act accordingly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $process->isSuccessful();$process->hasBeenSignaled();$process->hasBeenStopped();$process->isRunning();// new in 2.2$process->isStarted();$process->isTerminated();if(!$process->isRunning()){if($process->isStarted()&&!$process->isSuccessful()){$cloned=$process->restart();// ...}} |