【问题标题】:Redirecting STDERR in PHP exec在 PHP exec 中重定向 STDERR
【发布时间】:2014-10-23 06:18:53
【问题描述】:

我正在编写一个 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("STDOUT test", "STDERR test") 正如我所料,但在实时服务器上结果是 $status=1,并输出是一个空数组!

如果我删除 1>&2 部分,我会得到相同的结果(只是 STDOUT 部分),因此命令本身显然按预期工作。

我在这里缺少一些简单的东西吗?如果有帮助,服务器正在运行 Windows Server 2008 R2。

【问题讨论】:

  • 也许你应该尝试使用_test.bat的绝对路径。
  • 感谢您的评论,刚刚尝试使用完整路径,我仍然得到相同的结果 - 只要我不尝试使用 2>&1 重定向 STDERR,该命令就可以工作。问题是,我需要捕获 STDERR!
  • 检查php.ini中的display_errors指令——它应该设置为stderr
  • 它设置为 1,我已将其更改为 stderr 但它仍然在做同样的事情
  • 您是否重新启动了您的网络服务器?如果没有,我认为您需要这样做。我只有一个建议。您可以尝试使用 php 的处理程序 (stackoverflow.com/a/6447599/499581)。

标签: php windows exec wamp windows-server-2008


【解决方案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&gt;&amp;1 以将所有输出重定向到 STDIN。要输出到文件,手册显示可以修改 $descriptorspec 数组,例如:2 =&gt; array("file", "stderr.log", "a")(虽然我还没有测试过)

这里的一个区别是,如果我想在 PHP 中检索输出,而不是获取数组中的所有行,我需要使用 stream_get_contents() 从流中读取。

我仍然不明白为什么使用exec() 会出现问题,但这种方法似乎在本地和服务器上都有效 - 如果有人知道为什么会这样,请告诉我!

【讨论】:

    【解决方案2】:

    $o = null; $r = null; exec("php test.php 2>&1", $o, $r ); 很简单

    【讨论】:

    • 是的,这也适用于 Windows,2>filename 也是如此
    猜你喜欢
    • 1970-01-01
    • 2011-01-20
    • 2015-11-07
    • 1970-01-01
    • 2012-12-16
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多