在PHP中,我正在使用exec()执行命令,如果成功获取URL,则返回;
$url = exec('report');
但是,如果出现问题,我想检查stderr。我怎么读这个流? 我想使用php:// stderr,但我不确定如何使用它。
答案 0 :(得分:68)
如果你想执行命令,同时获得stderr
和stdout
,而不是“合并”,解决方案可能会使用proc_open
,这提供了很高的控制水平正在执行的命令 - 包括管道stdin
/ stdout
/ stderr
的方法。
以下是一个示例:我们假设我们在test.sh
中有这个shell脚本,它写入stderr
和stdout
:
#!/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;
现在,让我们在temp.php
中编写一些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
"
答案 1 :(得分:36)
可能有用的小功能:
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 :(得分:6)
获得未合并的stdout / stderr的另一种方法。
$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);
如果你想忽略stdout并且只获得stderr,你可以试试这个:
exec("wget -O - http://www.youtube.com 2>&1 >/dev/null", $r_stderr);
答案 3 :(得分:1)
exec("{$command} 2>&1"
,$output
,$exitCode
);
将标准错误重定向到标准输出。
现在使用 $exitCode 来确定 $command 完成状态,以及 $output 包含与 $exitCode
相关的所有输出答案 4 :(得分:0)
用exec
做这些事情的简短方法是返回退出代码(命令状态)
请注意,我正在尝试列出一个不存在的目录/non-dir/
exec('ls /non-dir/', $out, $retval);
var_dump($retval);
输出
ls:无法访问'/ non-dir /':没有这样的文件或目录
int(2)
通常在基于Unix的系统中,大多数成功的状态代码是( 0 ),因此您可以检查$retval
来了解命令的状态。
要排除列出无效路径ls: cannot access '/non-dir/': No such file or directory
的错误,可以将 stderr 重定向为null
exec('ls /non-dir/ 2>/dev/null', $out, $retval);
var_dump($retval);
这将输出:
int(2)
如果在任何情况下都需要错误字符串以使用它,则可以将 stderr 重定向到 stdout 。
exec('ls /non-dir/ 2>&1', $out, $retval);
print_r($out);
var_dump($retval);
这将输出以下内容:
Array
(
[0] => ls: cannot access '/non-dir/': No such file or directory
)
int(2)