【问题标题】:Stdin from node to PHP script hangs从节点到 PHP 脚本的标准输入挂起
【发布时间】:2019-03-08 23:52:05
【问题描述】:

我正在尝试将节点进程中的内容通过管道传输到 PHP 脚本中,但由于某种原因它挂在 PHP 中并且似乎永远不会退出 test-stdin.php 中的 while 循环因此最终的 echo 语句 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);

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

【问题讨论】:

    标签: php node.js stdin


    【解决方案1】:

    如果我将 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}`);
    });
    

    【讨论】:

    • 这是在节点中关闭标准输入的正确方法。这将在需要的数据流上发送结束事件,以便 ($line = fgets($input_stream,4096)) 评估为 false 或读取 4096 个字节。 ca.php.net/manual/en/function.fgets.php
    猜你喜欢
    • 2021-12-13
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多