从节点到PHP脚本的标准输入挂起

时间:2019-03-08 23:52:05

标签: php node.js stdin

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

run.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);

enter image description here

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

1 个答案:

答案 0 :(得分:1)

仅当我将PHP stdin流设置为阻止而不是取消阻止(如您的示例中的stream_set_blocking($input_stream, 1);时),这对我来说才挂起。

设置完后,它会永远挂起,因为NodeJS端没有任何东西可以结束stdin流。

在NodeJS的stdin上调用.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}`);
});