如何使用 proc_open() 函数通过管道传输到 PHP 进程?
How to pipe to PHP process using the proc_open() function?
在这种情况下有两个 PHP 文件,stdin.php(子进程组件)和 proc_open.php(父进程组件),两者都存放在同一个域的public_html文件夹中。还有 Program 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文件,甚至没有PHPerror_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 Content-type: text/html; charset=UTF-8
尝试了 popen('php ' . __DIR__ . '/stdin.php', 'w')
,结果完全相同:无限循环错误打印与上面相同的字符串,没有错误,没有日志,也没有 stdin.php 执行的信号。
如果我对你的问题的理解正确,你想打开一个进程并将数据写入该进程的 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);
在这种情况下有两个 PHP 文件,stdin.php(子进程组件)和 proc_open.php(父进程组件),两者都存放在同一个域的public_html文件夹中。还有 Program 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文件,甚至没有PHPerror_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 Content-type: text/html; charset=UTF-8
尝试了 popen('php ' . __DIR__ . '/stdin.php', 'w')
,结果完全相同:无限循环错误打印与上面相同的字符串,没有错误,没有日志,也没有 stdin.php 执行的信号。
如果我对你的问题的理解正确,你想打开一个进程并将数据写入该进程的 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);