首页 > 解决方案 > 从节点到 PHP 脚本的标准输入挂起

问题描述

我正在尝试将节点进程中的内容通过管道传输到 PHP 脚本中,但由于某种原因它挂在 PHP 中并且似乎永远不会退出test-stdin.phpwhile中的循环,因此最终的 echo 语句永远不会运行。echo('Total input from stdin: ' . $text)

运行.js

const { spawn } = require('child_process');
const php = spawn('php', ['test-stdin.php'], {});

php.stdin.write('some input');
php.stdin.write("\n"); // As I understand, EOL is needed to stop processing
// Also tried the below, didn't work.
// ls.stdin.write(require('os').EOL);

php.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

php.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

test-stdin.php

$input_stream = fopen("php://stdin","r");
stream_set_blocking($input_stream, 0); // Also tried: stream_set_blocking(STDIN, 0);

$text="";

// It never exits this loop, for some reason?
while(($line = fgets($input_stream,4096)) !== false) {
    var_dump('Read from fgets: ', $line); // This dumps successfully "some input"
    $text .= $line;
}

// The below code is never reached, as it seems it's hanging in the loop above.
fclose($input_stream);
echo('Total input from stdin: ' . $text);

在此处输入图像描述

任何想法为什么它挂在那个循环内而不是达到最终的回声?我尝试将流设置为“非阻塞”模式,但似乎没有任何效果。

标签: phpnode.jsstdin

解决方案


如果我将 PHP 标准输入流设置为阻塞而不是像您的示例那样取消阻塞,这只会挂起stream_set_blocking($input_stream, 1);

有了这个设置,它就像我所期望的那样永远挂起,因为 NodeJS 端没有任何东西正在结束标准输入流。

从 NodeJS调用.end()标准输入似乎是缺少的,例如:

const { spawn } = require('child_process');
const php = spawn('php', ['test-stdin.php'], {});

php.stdin.write('some input');
php.stdin.write("\n"); // As I understand, EOL is needed to stop processing
// Also tried the below, didn't work.
// ls.stdin.write(require('os').EOL);
php.stdin.end();

php.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

php.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

推荐阅读