【问题标题】:Multiple writes to a process opened with proc_open多次写入使用 proc_open 打开的进程
【发布时间】:2012-07-22 20:31:32
【问题描述】:

所以我用$process = proc_open("my_process", $descriptors, $pipes);打开一个进程

然后我使用fwrite($pipes[0], "some_command");写入进程的标准输入

然后我必须使用fclose($pipes[0]); 关闭管道,然后才能使用$output = stream_get_contents($pipes[1]); 从管道标准输出中读取。如果我不关闭管道,我的 php 脚本将挂在此调用上。

但是一旦我收到了来自 stdout 的输出,如果我想向进程发送另一个命令……stdin 管道已关闭,所以我无法发送它。那么是否有可能以某种方式向进程发送另一个命令?

【问题讨论】:

    标签: php process exec proc-open


    【解决方案1】:

    听起来其他进程正在阻塞等待 STDIN 上的 EOL 或 EOF。你想执行什么?

    无论如何,这很有可能会解决这个问题:只需将\n 附加到您要发送到其他进程的命令中。

    例如

    $process = proc_open("my_process", $descriptors, $pipes);
    
    $command = "some_command";
    fwrite($pipes[0], $command."\n");
    
    // Fetch the contents of STDOUT
    

    现在,您可能还会遇到的一个问题是您使用的是stream_get_get_contents() - 它会在返回之前等待 EOF。您可能需要更加了解如何从 $pipes[1] 检索数据,使用 fgets() 并查找特定数量的行或字符串来指示输出的结束。

    如果你告诉我们你在执行什么,我也许可以给你一个更具体的答案。

    【讨论】:

    • 是的,另一个程序是一个交互式终端程序,有自己的shell。如果我“正常”启动这个其他程序,即。通过终端而不是通过 php proc_open 它会加载,然后显示一个命令提示符,如“my_program >>”,我可以对其运行命令。我尝试将 '\n' 附加到 $command,但它不起作用。它将挂在 stream_get_contents() 上。使用 fflush() 也不起作用,它只有在我关闭 $pipes[0] 时才起作用。
    • @Jim_CS 试试上面的代码,但之后只需echo fgetc($pipes[1]); - 只需尝试从其他程序的 STDOUT 中获取 1 个字符并在 PHP 中回显它。我的猜测是您的读取操作导致了阻塞,而不是其他进程等待更多输入/EOF。如果这不起作用,请尝试从其他进程的 STDERR 获取数据,它可能正在输出您想要的数据。
    • 另一个程序输出一些启动文本,例如'Modules loaded: abc, xyz, etc...'。因此,如果我使用带有 $output[] = fgets[$pipes[1]) 的 while 循环,它首先会得到大约 8 行启动文本。如果我使用了 fclose($pipes[0]) 它会给我处理我发送的命令的输出。但是,如果我附加一个 '\n' 或使用 flush() 它将获得 8 行启动文本,但是当它应该从我的命令中检索输出时会挂起。在我看来,我的命令没有被发送到程序的 STDIN,就好像它被发送一样,我将能够检索结果。
    • @Jim_CS AFAIK 在这种情况下任何fwrite() 调用都会立即将数据发送到程序,而我只是在使用proc_open() 执行一些交互式程序,它似乎确实有效。我认为这是一些您无法提供给我的自定义程序,所以我可以自己玩?解决此问题的一种可能(尽管非常丑陋)的方法是将 telnet/SSH 连接到您自己并以这种方式执行它,因为您正在处理的 PHP 流将是基于套接字的,因此您可以使用设置超时等,而且您会只需为所有 I/O 操作处理一个流
    • 这个程序叫做gap,它是一个开源代数数学程序。由于一些错误,最新版本不能与 proc_open 一起使用,但版本 4.4.12 可以,你可以在这里获得它,你需要这两个包 - ftp.gap-system.org/pub/gap/gap44/tar.gz/gap4r4p12.tar.gz ftp.gap-system.org/pub/gap/gap44/tar.gz/… ... 第一个包中有一个带有安装说明的自述文件,基本上你只需输入'configure'然后'./make',它很简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多