[nycphp-talk] fun with proc_open
Dan Cech
dcech at phpwerx.net
Wed Oct 5 17:09:54 EDT 2005
Hi all,
Firstly, apologies for the long email, I couldn't think of a less
verbose way to describe the issues I'm experiencing.
I'm in the midst of writing a little program for executing long-running
processes in the background from php and monitoring their output as they
run.
The problem I'm running into is that when I execute a process using
proc_open and try to read any output from stdout and stderr I am running
into some odd behavior.
This only seems to happen under windows, running the same script on my
debian server works as expected.
The first read from stdout is fine, but then it doesn't get any more
output from stdout until the end of the script.
Is there some issue with using stdout and stderr together in this way
that I don't know about?
My test code looks like this:
<?php
// allow script to run for 5 minutes
set_time_limit(300);
// maximum length of blocks to read from process
define('FREAD_LENGTH',1024*10);
$cmd = 'php '.dirname(__FILE__).DIRECTORY_SEPARATOR.'sleep.php';
$descriptorspec = array(
1 => array('pipe','w'), // stdout
2 => array('pipe','w'), // stderr
);
$process = proc_open($cmd,$descriptorspec,$pipes);
if (!is_resource($process)) {
echo 'failed'."\n";
exit(1);
}
// don't block process stdout or stderr
stream_set_blocking($pipes[1],0);
stream_set_blocking($pipes[2],0);
// don't buffer stdout or stderr
stream_set_write_buffer($pipes[1],0);
stream_set_write_buffer($pipes[2],0);
while (true) {
// read process stdout
$stdout = fread($pipes[1],FREAD_LENGTH);
if (strlen($stdout) > 0) {
echo 'stdout:'. $stdout;
flush();
}
// read process stderr
$stderr = fread($pipes[2],FREAD_LENGTH);
if (strlen($stderr) > 0) {
echo 'stderr:'. $stderr;
flush();
}
// end when both pipes are closed
if (feof($pipes[1]) && feof($pipes[2])) {
break;
}
// wait for more output
sleep(1);
}
// close process stdout and stderr
fclose($pipes[1]);
fclose($pipes[2]);
// grab exit code
$exitcode = proc_close($process);
echo 'exitcode:'. $exitcode ."\n";
// end of script
sleep.php is a simple script that outputs some data:
<?php
ob_implicit_flush();
echo('started'."\n");
for ($i = 1;$i <= 10;$i++) {
sleep(1);
echo($i."\n");
}
fwrite(STDERR,'done'."\n");
// end of script
Running the first script from command line or web browser should output:
stdout:started
stdout:1
stdout:2
stdout:3
stdout:4
stdout:5
stdout:6
stdout:7
stdout:8
stdout:9
stdout:10
stderr:done
exitcode:0
On windows I'm seeing:
stdout:started
stderr:done
stdout:1
2
3
4
5
6
7
8
9
10
exitcode:0
I've managed to get the same functionality using popen and redirecting
stderr to a fifo or tempfile, but proc_open seems like the cleaner
solution if I can get it to work the way I want.
Any ideas?
Dan
More information about the talk
mailing list