2

我想说这是一个非常简单的问题,但我坚持下去:

我需要与使用一些调试选项运行的外部程序(特别是 Exim)进行通信。当我从 linux shell 运行它时,它是这样的:运行exim -bh 11.22.33.44,然后读取它的输出(STDOUT 和 STDERR),从 SMTP 对话框中输入某行,然后再次读取 Exim 输出,输入另一个 SMTP 行等等。它在我使用 bash shell 时运行良好,但是当我从 PHP 脚本运行它时,它卡在了 STDIN 读取循环中。

我使用proc-open

$descriptorspec = array(
    0 => array("pipe", "r"), 
    1 => array("pipe", 'w'), 
    2 => array("pipe", 'w')
);
$process=proc_open('/usr/sbin/exim -bh 11.22.33.44', $descriptorspec, $pipes, NULL, NULL);
if (is_resource($process)) {
    stream_set_blocking($pipes[1], 1);
    stream_set_blocking($pipes[2], 1);
    while(!feof($pipes[2])) {
        $txt2 = fgets($pipes[2]);
    }
    while(!feof($pipes[1])) {
        $txt2 = fgets($pipes[1]);
    }
    fwrite($pipes[0], 'HELO testhost');
...
}

看起来很简单,但在第一个 STDERR 结束时,它卡住了。

尝试了阻塞和解除阻塞模式,尝试从 STDERR 和 STDIN 交换读取 - 到目前为止没有运气。

请指出正确的方法!

4

1 回答 1

0

我仔细检查以确保 exim 没有对 STDIN、STDOUT 和 STDERR 做任何奇怪的事情。另外,我知道你可以使用 swaks 来管道到 STDIN 和从 STDOUT (STDERR 是调试输出,所以你可以忽略它)。使用 swaks,通常使用以下命令测试调试版本:

swaks --pipe './build-Linux-i386/exim -bh 205.201.128.129 
              -C/work/home/exim-build/tmp/etc/exim/exim.conf'
  --ehlo twitter4.us4.mcsv.net 
  --from bounce-mc.us3_23284199.312009-user=example.com@twitter4.us4.mcsv.net
  --to localuser@example.net --data $HOME/12.eml

您的脚本正在检查 EOF,它仅在管道关闭时发送。相反,您需要构建一个函数,外部循环检查 for() 从其中一个管道检查 !eof() 。在循环内部,检查 STDERR 和 STDOUT 的输出,如果找到则显示。当它到达它期望输入的点时,然后发送您的 SMTP 命令。

不过还是有问题。如果您使用 print $txt2 来查看它在做什么,不知何故,该输出似乎与 fprintf($pipes[0]...) 相同。我不知道为什么,而且我不是 php 程序员,也不知道为什么会这样做。

于 2014-06-04T16:14:23.807 回答