Stdin от узла к PHP-скрипту зависает - PullRequest
0 голосов
/ 09 марта 2019

Я пытаюсь передать содержимое процесса узла в скрипт PHP, но по какой-то причине он зависает в PHP и, похоже, никогда не выходит из цикла while в test-stdin.php и поэтому окончательное эхо-выражение 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}`);
});

тест-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 Ответ

1 голос
/ 09 марта 2019

Это зависнет только для меня, если я установлю поток PHP stdin как блокирующий, а не разблокирующий, как, например, в вашем примере, например, stream_set_blocking($input_stream, 1);.

С этим набором он зависает навсегда, как я и ожидал, поскольку ничто на стороне NodeJS не заканчивает поток stdin.

Вызов .end() на stdin из NodeJS, кажется, все, чего не хватает, например:

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}`);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...