【问题标题】:How to pipe to PHP process using the proc_open() function?如何使用 proc_open() 函数通过管道传输到 PHP 进程?
【发布时间】:2015-10-08 16:42:53
【问题描述】:

本例中有两个PHP文件,stdin.php(子进程组件)和proc_open.php(父进程组件),都存放在同一个域的 public_html 文件夹。还有Program X,将数据通过管道传输到stdin.php。


stdin.php(此组件有效)

这是一个不应通过浏览器执行的进程,因为它注定要接收来自 Program X 的输入,并将其全部备份到一个文件中(名为 stdin_backup)。 此进程正在运行,因为每次 Program 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(此组件不工作)

这是一个必须通过浏览器执行的进程,并且注定要像 Program 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执行的信号。

【问题讨论】:

    标签: php pointers pipe stdin


    【解决方案1】:

    如果我正确理解您的问题,您想打开一个进程并将数据写入该进程的 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);
    

    【讨论】:

      猜你喜欢
      • 2019-06-20
      • 2011-08-09
      • 1970-01-01
      • 2015-02-28
      • 1970-01-01
      • 2023-03-08
      • 2014-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多