我正在编写一个PHP脚本,需要对外部命令行实用程序进行一些调用,我使用的是exec()。如果它在本地工作正常,但当我将它移动到实时服务器时,它不再有效。
经过一些调试后,我认为问题归结为STDERR重定向 - 如果我尝试重定向(重定向到STDIN,重定向到文件),命令完全失败。
我写了一个简单的bat脚本来简化测试:
@echo off
echo STDOUT test
echo STDERR test 1>&2
然后在PHP中:
<?php
$cmd = "_test.bat 2>&1";
exec($cmd, $output, $status);
var_dump($output);
var_dump($status);
?>
在本地服务器上,结果是$ status = 0,$ output = array(&#34; STDOUT test&#34;,&#34; STDERR test&#34;),正如我所料,但在实时服务器上结果是$ status = 1,输出是一个空数组!
如果我删除1&gt;&amp; 2部分,我得到两者的相同结果(只是STDOUT部分),所以命令本身显然正常工作。
我在这里缺少一些简单的东西吗?如果有帮助,则服务器正在运行Windows Server 2008 R2。
答案 0 :(得分:3)
$o = null;
$r = null;
exec("php test.php 2>&1", $o, $r );
这很简单
答案 1 :(得分:1)
更新并回答任何来这里遇到类似问题的人的利益。
在花了很多时间之后,我放弃了exec()
并尝试了proc_open()
。
这样做现在可以在本地和服务器上运行:
<?php
$cmd = "__test.bat";
$descriptorspec = array(
0 => array("pipe", "r"), // STDIN
1 => array("pipe", "w"), // STDOUT
2 => array("pipe", "w"), // STDERR
);
$cwd = getcwd();
$env = null;
$proc = proc_open($cmd, $descriptorspec, $pipes, $cwd, $env);
if (is_resource($proc)) {
// Output test:
echo "STDOUT:<br />";
echo "<pre>".stream_get_contents($pipes[1])."</pre>";
echo "STDERR:<br />";
echo "<pre>".stream_get_contents($pipes[2])."</pre>";
$return_value = proc_close($proc);
echo "Exited with status: {$return_value}";
}
?>
由于某种原因,错过getcwd()
部分会导致命令在服务器上失败,除非我指定完整路径,而本地则不是问题。
使用此方法,我可以附加2>&1
将所有输出重定向到STDIN。要输出到文件,手册显示可以修改$ descriptorspec数组,例如:2 => array("file", "stderr.log", "a")
(我还没有测试过这个)
这里的一个区别是,如果我想在PHP中检索输出,而不是获取数组中的所有行,我需要使用stream_get_contents()
读取流。
我仍然不明白为什么使用exec()
会出现问题,但这种方法似乎在本地和服务器上都有效 - 如果有人知道为什么会这样,请告诉我!