3

我一直在使用 PHP 在 Apache 服务器中执行旧脚本。旧脚本将调试数据写入 STDERR,我一直根据调试设置将其重定向到黑洞或 STDOUT。

PHP 看起来有点像这样:

exec('perl -e "print 10; print STDERR 20" 2>&1', $output);

在 XP 中可靠地工作。我得到了现在运行 windows7 的新硬件,回到这段代码它被破坏了。零输出。返回码 255。不知道为什么。

我能够让它再次运行的唯一方法是删除重定向。哦,重定向仍然可以在终端盒中完美运行。

现在我必须从 apache-error-log 中检索我的调试数据(默认情况下每个 STDERR 输出都在其中),这很不方便,但不是问题。

我只是想了解为什么重定向突然停止工作(也许可以帮助其他人遇到同样的问题)。apache 是一样的,实际上我只是从旧盒子中复制了 XAMPP 目录。一个错误?系统限制?操作系统政策禁止?

4

2 回答 2

1

与其使用exec和使用文件句柄重定向,不如使用proc_open并实际捕获 stdout 和 stderr 的输出。与一些与进程相关的函数不同,该proc_家族内置于所有版本的 PHP 中,并且在 Windows 上运行良好。

为了完整性,他们的示例的 c&p:

$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);

$cwd = '/tmp';
$env = array('some_option' => 'aeiou');

$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);

if (is_resource($process)) {
    // $pipes now looks like this:
    // 0 => writeable handle connected to child stdin
    // 1 => readable handle connected to child stdout
    // Any error output will be appended to /tmp/error-output.txt

    fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    fclose($pipes[0]);

    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // It is important that you close any pipes before calling
    // proc_close in order to avoid a deadlock
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
}

请务必在文档页面上浏览用户提供的赞成意见,以了解可能的警告

于 2013-08-12T04:44:01.357 回答
0

好的,我得到了(也许至少是我的)解决方案:

  1. 按照查尔斯的建议使用 proc_open
  2. 回到原来的io_redirection原理

将东西直接转储到 STDERR 并通过管道从那里检索它显然不适用于(我的)windows7+PHP 和我的代码。简单的例子有效,但对我来说就是这样。

所以在使用2>&1时破坏了我的 exec() - 最初的问题 - 它与 proc_open() 配合得非常好。问题解决了。

我想知道我现在是否会在运行新代码的 linux 服务器上发现有问题。

小警告:如果您不希望您的代码打印到 STDERR 并且您使用重定向到 null 例如用于生产,在 Windows 中它是2>nul

于 2013-08-19T15:00:28.597 回答