Reputation: 1290
I've tried to get output from proc_open
method in php, but, when I print it, I got empty.
$descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("file", "files/temp/error-output.txt", "a") ); $process = proc_open("time ./a a.out", $descriptorspec, $pipes, $cwd);
as long as I know, I can get the output with stream_get_contents()
echo stream_get_contents($pipes[1]); fclose($pipes[1]);
But I can't do that.. any suggestion?
Thx before...
Upvotes: 17
Views: 34202
Reputation: 1005
Here is a complete functions which reads stdout and stderr.
/**
* Executes process
*
* @param string $command
* @param string $cwd
* @param bool $exitOnError
* @return void
*/
function exec(string $command, string $cwd, bool $exitOnError = true): void
{
$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);
if (is_resource($process)) {
do {
$read = array($pipes[1], $pipes[2]);
$write = null;
$except = null;
$status = proc_get_status($process);
if ($status['running'] === false) {
break;
}
if (stream_select($read, $write, $except, 5)) {
foreach ($read as $c) {
if (feof($c) || fstat($c)['size'] === 0) {
continue;
}
$read = fread($c, 1024);
if ($read === false) {
continue;
}
echo $read;
}
}
} while (!feof($pipes[1]) | !feof($pipes[2]));
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
// It is important to close any pipes before calling
// proc_close to avoid a deadlock
$returnValue = proc_close($process);
if ($returnValue != 0) {
if ($exitOnError) {
exit(1);
}
}
} else {
echo "Couldn't open $command";
if ($exitOnError) {
exit(1);
}
}
}
Upvotes: 1
Reputation: 326
this is another example with proc_open()
.
I am using Win32 ping.exe command in this example. CMIIW
set_time_limit(1800);
ob_implicit_flush(true);
$exe_command = 'C:\\Windows\\System32\\ping.exe -t google.com';
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout -> we use this
2 => array("pipe", "w") // stderr
);
$process = proc_open($exe_command, $descriptorspec, $pipes);
if (is_resource($process))
{
while( ! feof($pipes[1]))
{
$return_message = fgets($pipes[1], 1024);
if (strlen($return_message) == 0) break;
echo $return_message.'<br />';
ob_flush();
flush();
}
}
Hope this helps =)
Upvotes: 12
Reputation: 7507
Your code more or less works for me. time
prints its output to stderr
so if you're looking for that output, look in your file files/temp/error-output.txt
. The stdout
pipe $pipes[1]
will only contain the output of the program ./a
.
My repro:
[edan@edan tmp]$ cat proc.php
<?php
$cwd='/tmp';
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "/tmp/error-output.txt", "a") );
$process = proc_open("time ./a a.out", $descriptorspec, $pipes, $cwd);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
?>
[edan@edan tmp]$ php proc.php
a.out here.
[edan@edan tmp]$ cat /tmp/error-output.txt
real 0m0.001s
user 0m0.000s
sys 0m0.002s
Upvotes: 13