New in Symfony 2.2: Process Component Enhancements
January 10, 2013 • Published by Fabien Potencier
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
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);
}
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();
// ...
}
}
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.