与PHP的外部程序进行交互

时间:2014-06-04 14:26:59

标签: php external exim proc-open

我说这是一个非常简单的问题,但我坚持不懈:

我需要使用一些调试选项与外部程序(特别是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交换读取 - 到目前为止没有运气。

请指出正确的方法!

1 个答案:

答案 0 :(得分:0)

我仔细检查以确保exim不会使用STDIN,STDOUT和STDERR做任何有趣的事情。另外,我知道你可以使用swak来管道传输到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,该EOF仅在管道关闭时发送。相反,你需要构造一个外部循环检查for()的函数来检查来自其中一个管道的!eof()。在循环内部,检查STDERR和STDOUT的输出,如果找到则显示它。当它到达预期输入的点时,然后发送您的SMTP命令。

但仍有一个问题。如果您使用print $ txt2来查看它正在做什么,那么输出似乎与fprintf($ pipes [0] ...)相同。我不确定为什么,而且我不是一个知道为什么会这样做的PHP程序员。