我有一个应用程序(通常的.exe文件),我可以在控制台中运行(例如作为守护进程)。它工作正常,输入/输出只是标准的STDIN / STDOUT,所以从控制台(windows或debian)没有问题。但我需要与php(我的PHP脚本)进行交互。
这也没问题,因为PHP中有很多'东西'可以做到这一点(proc_open,exec,系统,管道,字符串等等)。问题是应用程序在获取/接收数据期间必须工作(简单来说 - 这是一个守护进程),但上面的所有函数都在等待命令的执行结束和返回结果之后。
来自php.net
注意: 如果程序是使用此功能启动的,则为了使其在中继续运行 后台,程序的输出必须重定向到文件或另一个输出
流。如果不这样做将导致PHP挂起,直到执行程序 结束。
众所周知如何使用>
|
&
等重定向到另一个输入/输出(例如文件):
$last_line = system("myfile.exe>file2.txt", $retval);
即使作为守护进程也能正常工作。虽然我无法得到如何在模式中实现输入。 但是,我的主要问题是如何将标准输出重定向到非文件资源。 在php.net上写道:
Windows兼容性:超过2(stderr)的描述符可作为可继承句柄提供给子进程,但由于Windows体系结构不将文件描述符编号与低级句柄相关联,因此子进程(尚未)具有访问这些句柄的方法。 Stdin,stdout和stderr按预期工作。
所以它只是简单command>&3
但我不能为I / O定义新的(我自己的)句柄。
所以问题是How to implement/handle input/output (to BOTH ways) for a daemon!!!
我在互联网上仔细检查了很多来源,但没有得到PHP的正常答案。它是Java的基础,例如,C / C ++而不是PHP。
也许有人帮助我 - 我会非常感激!
答案 0 :(得分:0)
proc_*
函数比您预期的更强大。你假设这些函数会阻塞是不正确的。
调用proc_open
后,您可以将每个管道设置为非阻塞。这将导致您无需等待流程输入就可以使用fread
,并尝试fwrite
而无需等待流程接受它。
另外,我建议使用socket_select
来确保您没有进入紧急循环,尝试读取/写入已执行的进程。当文件指针(在你的情况下是管道)准备好阅读或被写入时,选择结构将打破它的睡眠时间。
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("file", "r") // stderr );
$process = proc_open('php', $descriptorspec, $pipes);
foreach($pipes as $pipe)
stream_set_blocking($pipe, 0);
有关详细信息,请参阅socket_select,stream_set_blocking和proc_open的文档和评论。