2010-02-23 64 views
43

在PHP中,我使用exec()执行一个命令,并且在成功的情况下返回一个URL;Exec后PHP StdErr()

$url = exec('report'); 

但是,我想检查stderr,如果出了问题。我如何阅读流? 我想使用php:// stderr,但我不确定如何使用它。

+0

我会推荐你​​使用Symfony/Process组件。 – 2018-02-06 18:03:35

回答

65

如果要执行命令,并同时获得stderrstdout,而不是“合并”,一个解决办法可能是使用proc_open,它提供了真实执行过的命令控制的一个伟大的水平 - 包括路到管道stdin/stdout/stderr


这里有一个例子:让我们来看看,我们有这个shell脚本,在test.sh,其中写入到两个stderrstdout

#!/bin/bash 

echo 'this is on stdout'; 
echo 'this is on stdout too'; 

echo 'this is on stderr' >&2; 
echo 'this is on stderr too' >&2; 


现在,让我们一些代码PHP,在temp.php - 首先,初始化I/O描述符:

$descriptorspec = array(
    0 => array("pipe", "r"), // stdin 
    1 => array("pipe", "w"), // stdout 
    2 => array("pipe", "w"), // stderr 
); 


,然后,执行test.sh命令,使用这些描述符,在当前目录下,并说了I/O应自/至$pipes

$process = proc_open('./test.sh', $descriptorspec, $pipes, dirname(__FILE__), null); 


现在,我们可以从两个输出管道读:

$stdout = stream_get_contents($pipes[1]); 
fclose($pipes[1]); 

$stderr = stream_get_contents($pipes[2]); 
fclose($pipes[2]); 


而且,如果我们输出这两个变量的内容:

echo "stdout : \n"; 
var_dump($stdout); 

echo "stderr :\n"; 
var_dump($stderr); 


我们执行temp.php脚本时得到以下输出:

$ php ./temp.php 
stdout : 
string(40) "this is on stdout 
this is on stdout too 
" 
stderr : 
string(40) "this is on stderr 
this is on stderr too 
" 


希望这有助于:-)

+3

使用这个时,确保所有的人都使用proc_close,当你完成清洁的时候。 – 2011-10-27 21:45:40

+0

为什么你将结果重定向到一个进程var? – 2012-11-07 12:53:32

+3

@BriceFavre他把它放在一个进程变量中,以便他可以稍后用proc_close关闭它,这也将返回进程退出的返回代码。 '$ returnCode = proc_close($ process);' – 2013-03-04 20:15:58

6

另一种方式来获得未合并标准输出/标准错误。

$pp_name = "/tmp/pp_test"; 
@unlink($pp_name); 
posix_mkfifo($pp_name, 0777); 
$pp = fopen($pp_name, "r+"); 
stream_set_blocking($pp, FALSE); 
exec("wget -O - http://www.youtube.com 2>$pp_name", $r_stdout); 
$r_stderr = stream_get_contents($pp); 
var_dump($r_stderr); 
fclose($pp); 
unlink($pp_name); 

如果你想忽略标准输出并获得唯一标准错误,你可以试试这个:

exec("wget -O - http://www.youtube.com 2>&1 >/dev/null", $r_stderr); 
30

一个小功能可能会有所帮助:

function my_shell_exec($cmd, &$stdout=null, &$stderr=null) { 
    $proc = proc_open($cmd,[ 
     1 => ['pipe','w'], 
     2 => ['pipe','w'], 
    ],$pipes); 
    $stdout = stream_get_contents($pipes[1]); 
    fclose($pipes[1]); 
    $stderr = stream_get_contents($pipes[2]); 
    fclose($pipes[2]); 
    return proc_close($proc); 
} 

返回的退出代码如果你需要它们,STDOUT和STDERR是参考参数。

+2

不错,简单,完美。感谢发布! – 2015-01-07 21:56:00