如何使用proc_open()函数管道到PHP进程?

时间:2015-10-08 16:42:53

标签: php pointers pipe stdin

在这种情况下,有两个PHP文件, stdin.php (子进程组件)和 proc_open.php (父进程组件),两者都存储在同一个文件中域的public_html的文件夹。还有程序X ,它将数据传输到stdin.php。

stdin.php (此组件有效)

这是一个不应该通过浏览器执行的进程,因为它的目的是接收来自程序X的输入,并将其全部备份到一个文件(名为stdin_backup)中。 此过程正在运行,因为每次程序X管道输入时,该过程都会完全备份。如果在未传递输入的情况下执行此过程(例如从浏览器执行此操作),则该过程将创建一个文件(名为stdin_error),其中包含文本" ERROR"。

下面,部分代码被省略,因为该过程有效(如上所述)。显示的代码只是为了说明:

#!/usr/bin/php -q
<?php
   // Get the input
    $fh_stdin = fopen('php://stdin', 'rb');

    if (is_resource($fh_stdin)) {
        // ... Code that backs up STDIN in a file ...
    } else {
        // ... Code that logs "ERROR" in a file ...
    }
?>

proc_open.php (此组件无效)

这是一个必须通过浏览器执行的进程,并且正如程序X所做的那样,目的是将输入传递给stdin.php。此过程失败,因为每次执行时都没有执行stdin.php的信号:没有stdin_error文件,没有stdin_backup文件,甚至没有PHP error_log文件。

代码:

// Execute a PHP process and pipe input to it
//  - Specify process command
$process_path = __DIR__ . '/stdin.php';
$process_execution_command = 'php ' . $process_path;

//  - Specify process descriptor
$process_descriptor = array(
    0 => array('pipe', 'r') // To child's STDIN
);

//  - Specify pipes container
$pipes = [];

//  - Open process
$process = proc_open($process_execution_command, $process_descriptor, $pipes);

if (is_resource($process)) {
    //  - Send data to the process STDIN
    $process_STDIN = 'Data to be received by the process STDIN';
    fwrite($pipes[0], $process_STDIN);
    fclose($pipes[0]);

    //  - Close process
    $process_termination_status = proc_close($process);
}

我不确定传递给proc_open()的命令是否正确,因为我没有找到这种情况的例子,如上所述,这个脚本失败了。我不知道proc_open.php还有什么不对。

当我执行proc_open.php进程时,会产生一个无限循环,一遍又一遍地打印下一个字符串:

  

X-Powered-By:PHP / 5.5.20内容类型:text / html;字符集= UTF-8

尝试使用popen('php ' . __DIR__ . '/stdin.php', 'w'),并且具有相同的结果:无限循环错误打印上面的相同字符串,没有错误,没有日志,也没有stdin.php执行的信号。

1 个答案:

答案 0 :(得分:3)

如果我理解你的问题,你想打开一个进程并将数据写入该进程的STDIN流。您可以使用proc_open函数:

$descriptors = array(
    0 => array("pipe", "r"),  // STDIN
    1 => array("pipe", "w"),  // STDOUT
    2 => array("pipe", "w")   // STDERR
);

$proc = proc_open("php script2.php", $descriptors, $pipes);
fwrite($pipes[0], "Your data here...");
fclose($pipes[0]);

$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);

fclose($pipes[1]);
fclose($pipes[2]);

$exitCode = proc_close($proc);

如果您只是想测试第二个脚本,那么简单地使用shell命令可能会更容易:

$ echo "your data" | php script2.php

或者,

$ php script2.php < datafile.txt

更新,记录您对问题的修改

使用popen功能时,您可以打开读取或写入过程。这允许您读取进程'STDOUT流或写入STDIN流(但不是两者;如果这是一个要求,则需要使用proc_open)。如果要写入STDIN流,请将"w"指定为popen的第二个参数以打开写入过程:

$fh_pipe = popen(
    'php script1.php',
    'w'   // <- "w", not "r"!
);

fwrite($fh_pipe, 'EMAIL TEXT') ;
pclose($fh_pipe);