В качестве простого доказательства концепции я попытался разделить строку между разветвленными процессами от узла к узлу или от узла к php.
Возьмите этот простой PHP-код, который должен регистрировать вывод stdin
в соответствии с PHP документы:
echo 'test' | php -r 'echo trim(fgets(STDIN));'
Работает нормально, но когда я запускаю процесс из nodejs:
var fs = require('fs'); var spawn = require('child_process').spawn;
//dummy stdin file
var stdin = fs.openSync('stdin_file', 'w+');
//write the string
fs.writeSync(stdin, 'test');
spawn('php', ['stdin_test.php'], {
cwd: __dirname,
detached: true,
//to fully detach the process nothing should be piped from or to the parent process
stdio: [stdin, fs.openSync('out.log', 'a'), fs.openSync('err.log', 'a')]
})
<?php
error_log('php://stdin');
//this should log 'test' but outputs a newline
error_log(trim(fgets(STDIN)));
$t = fopen('/dev/stdin', 'r');
error_log('/dev/stdin:');
//this is working as expected
error_log(trim(fgets($t)));
Почему php://stdin
пусто? Безопасно ли использовать /dev/stdin
? В чем разница между /dev/stdin
а также php://stdin
тем не мение?
Обратите внимание, что у меня есть такое поведение также между процессами с двумя узлами: process.stdin
пусто, но /dev/stdin
имеет ожидаемый результат.
Я тестировал с помощью следующего скрипта ( stdin_test.php
) с помощью:
> echo test | php stdin_test.php
<?
echo 'STDIN :' ;
echo trim(fgets(STDIN)) ;
echo PHP_EOL;
$stdin_stream = fopen('php://stdin', 'r');
echo 'php://stdin :';
echo trim(fgets($stdin_stream));
echo PHP_EOL;
fclose($stdin_stream);
$stdin_file = fopen('/dev/stdin', 'r');
echo '/dev/stdin :';
echo trim(fgets($stdin_file));
echo PHP_EOL;
fclose($stdin_file);
Я вернусь :
STDIN :test
php://stdin :
/dev/stdin :
Если я тогда закомментирую строку:
//echo trim(fgets(STDIN));
Я вернусь:
STDIN :
php://stdin :test
/dev/stdin :
Если я закомментирую оба первых эха stdin (и указатели на обработчик файлов), я получу:
STDIN :
php://stdin :
/dev/stdin : test
Глядя на документацию по php://input
и как его можно использовать один раз, если (после 5.6) «тело запроса не сохранено», что типично для запросов POST, но не для запросов PUT (очевидно). Это заставляет меня думать, что они называются «потоками», потому что вы однажды можете в них ходить.
Перемотайте ваш поток stdin в JS перед порождением PHP, иначе указатель файла будет находиться в конце того, что вы только что написали.