note 94563 deleted from function.proc-open by danbrown
| From: | danbrown@php.net | Date: | Thu, 12 Nov 2009 13:32:56 +0000 |
| Subject: | note 94563 deleted from function.proc-open by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-162805@lists.php.net to get a copy of this message | ||
Note Submitter: gabelager at gabelager dot net
----
Here is a combined implementation of the example code and the comments from simeonl at dbc dot co
dot nz
04-Mar-2009 02:39
<?php
function openProcess($command, $cwd = NULL, $env = NULL)
{
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
//$pipes now looks like this:
//0 => writeable handle connected to child stdin
//1 => readable handle connected to child stdout
//2 => readable handle connected to child stderr
//Some excellent pipe-reading code that prevents deadlocks.
//Taken verbatim (and cleaned-up for formatting) from:
//http://us3.php.net/manual/en/function.proc-open.php#89338
$readOutput = $readError = false;
$bufferLen = $prev_buffer_len = 0;
$ms = 10;
$output = '';
$readOutput = true;
$error = '';
$readError = true;
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
//Dual reading of STDOUT and STDERR stops one full pipe blocking the other,
//because the external script is waiting.
while ($readError != false or $readOutput != false) {
if ($readOutput != false) {
if (feof($pipes[1])) {
fclose($pipes[1]);
$readOutput = false;
} else {
$str = fgets($pipes[1], 1024);
$len = strlen($str);
if ($len) {
$output .= $str;
$bufferLen += $len;
}
}
}
if ($readError != false) {
if (feof($pipes[2])) {
fclose($pipes[2]);
$readError = false;
} else {
$str = fgets($pipes[2], 1024);
$len = strlen($str);
if ($len) {
$error .= $str;
$bufferLen += $len;
}
}
}
if ($bufferLen > $prev_buffer_len) {
$prev_buffer_len = $bufferLen;
$ms = 10;
} else {
usleep($ms * 1000); // sleep for $ms milliseconds
if ($ms < 160) {
$ms = $ms * 2;
}
}
}
//Pipes 1 and 2 have already been closed.
fclose($pipes[0]);
//It is important to close any pipes before calling
//proc_close in order to avoid a deadlock.
$retVal['exitCode'] = proc_close($process);
$retVal['stdOut'] = $output;
$retVal['stdErr'] = $error;
return $retVal;
}
else {
return FALSE;
}
}
?>