Library for executing child processes.
This library integrates Program Execution
with the EventLoop.
Child processes launched may be signaled and will emit an
exit event upon termination.
Additionally, process I/O streams (i.e. STDIN, STDOUT, STDERR) are exposed
as Streams.
Table of contents
exit: Emitted whenever the process is no longer running. Event listeners will receive the exit code and termination signal as two arguments.
start(): Launches the process and registers its IO streams with the event loop. The stdin stream will be left in a paused state.terminate(): Send the process a signal (SIGTERM by default).
There are additional public methods on the Process class, which may be used to
access fields otherwise available through proc_get_status().
Once a process is started, its I/O streams will be constructed as instances of
React\Stream\Stream. Before start() is called, these properties are null.
Once a process terminates, the streams will become closed but not unset.
$stdin$stdout$stderr
Each of these implement the underlying
DuplexStreamInterface
and you can use any of its events and methods as usual:
$process->stdout->on('data', function ($chunk) {
echo $chunk;
});
$process->stdout->on('end', function () {
echo 'ended';
});
$process->stdout->on('error', function (Exception $e) {
echo 'error: ' . $e->getMessage();
});
$process->stdout->on('close', function () {
echo 'closed';
});
$process->stdin->write($data);
$process->stdin->end($data = null);
$process->stdin->close();
// …For more details, see the
DuplexStreamInterface.
$loop = React\EventLoop\Factory::create();
$process = new React\ChildProcess\Process('echo foo');
$process->on('exit', function($exitCode, $termSignal) {
// ...
});
$loop->addTimer(0.001, function($timer) use ($process) {
$process->start($timer->getLoop());
$process->stdout->on('data', function($output) {
// ...
});
});
$loop->run();Symfony pull request #5759
documents a caveat with the
Program Execution extension. PHP will
launch processes via sh, which obfuscates the underlying process' PID and
complicates signaling (our process becomes a child of sh). As a work-around,
prepend the command string with exec, which will cause the sh process to be
replaced by our process.
When PHP has been compiled with the --enabled-sigchild option, a child
process' exit code cannot be reliably determined via proc_close() or
proc_get_status(). Instead, we execute the child process with a fourth pipe
and use that to retrieve its exit code.
This behavior is used by default and only when necessary. It may be manually
disabled by calling setEnhanceSigchildCompatibility(false) on the Process
before it is started, in which case the exit event may receive null instead
of the actual exit code.
Note: This functionality was taken from Symfony's Process compoment.
Command chaning with && or ;, while possible with proc_open(), should not
be used with this component. There is currently no way to discern when each
process in a chain ends, which would complicate working with I/O streams. As an
alternative, considering launching one process at a time and listening on its
exit event to conditionally start the next process in the chain. This will
give you an opportunity to configure the subsequent process' I/O streams.
The recommended way to install this library is through Composer. New to Composer?
This will install the latest supported version:
$ composer require react/child-process:^0.4.2More details about version upgrades can be found in the CHANGELOG.
To run the test suite, you first need to clone this repo and then install all dependencies through Composer:
$ composer installTo run the test suite, go to the project root and run:
$ php vendor/bin/phpunitMIT, see LICENSE file.
