Archives


Master Symfony2 fundamentals

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Symfony hosting done right

ServerGrove, outstanding support at the right price for your Symfony hosting needs.
servergrove.com

Discover the SensioLabs Support

Access to the SensioLabs Competency Center for an exclusive and tailor-made support on Symfony
sensiolabs.com

Fabien Potencier
New in Symfony 2.2: Process Component Enhancements
by Fabien Potencier – January 10, 2013 – 2 comments

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
use Symfony\Component\Process\Process;

$process = new Process('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
use Symfony\Component\Process\Process;

$processes = array();
$processes[] = new Process('ls -lsa');
$processes[] = new Process('ps waux');

while (count($processes) > 0) {
     foreach ($processes as $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);
}
Jimmy Berry

Contributed by
Jimmy Berry
in #5456 and #5455.

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
use Symfony\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();

        // ...
    }
}

Comments RSS

  • Matthew Haworth
    #1 Matthew Haworth said on the 2013/01/10 at 14:54
    I made a pull request for a method that returns the process id, any chance you could have a look?
  • Thomas Lallement
    #2 Thomas Lallement said on the 2013/01/10 at 23:11
    I love this kind of news!