我说这是一个非常简单的问题,但我坚持不懈:
我需要使用一些调试选项与外部程序(特别是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交换读取 - 到目前为止没有运气。
请指出正确的方法!
答案 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程序员。