her's a function that is similar to shell_exec but captures both stdout and stderr. It's much more complicated than using 2>&1, but it's independent of the shell and should work on windows, too. It uses proc_open with stream_select and non-blocking streams to read stdout and stderr concurrently. It is not guarantied that the lines appear in the correct order or that they are not intermingeled - but it did not happened when I tested it. So, here goes:
<?php
function runExternal($cmd,&$code) {
$descriptorspec = array(
0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") );
$pipes= array();
$process = proc_open($cmd, $descriptorspec, $pipes);
$output= "";
if (!is_resource($process)) return false;
fclose($pipes[0]);
stream_set_blocking($pipes[1],false);
stream_set_blocking($pipes[2],false);
$todo= array($pipes[1],$pipes[2]);
while( true ) {
$read= array();
if( !feof($pipes[1]) ) $read[]= $pipes[1];
if( !feof($pipes[2]) ) $read[]= $pipes[2];
if (!$read) break;
$ready= stream_select($read, $write=NULL, $ex= NULL, 2);
if ($ready === false) {
break; }
foreach ($read as $r) {
$s= fread($r,1024);
$output.= $s;
}
}
fclose($pipes[1]);
fclose($pipes[2]);
$code= proc_close($process);
return $output;
}
?>
here is how to use it:
<?php
$result= runExternal("ls -l some-file.txt",$code);
print "<pre>";
print $result;
print "</pre>\n";
print "<b>code: $code</b>\n";
?>
enjoy :-)