作为一个简单的概念证明,我尝试在节点之间或从节点到php的分叉进程之间共享一个字符串。
根据php docs,使用这个简单的PHP代码来记录stdin
的输出:
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
具有预期结果。
答案 0 :(得分:2)
我使用以下脚本(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请求(显然)。这让我觉得它们被称为“溪流”,因为你可以一次走进它们。
答案 1 :(得分:0)
在生成PHP之前在JS中回放你的stdin流,否则文件指针将位于你刚才写的结尾。