Trying to understand the difference between / dev / stdin and php: // stdin

As a simple proof of concept, I tried to split the string between forked processes from node to node or from node to php.

Take this simple php code that should log the output stdin

according to the php docs :

echo 'test' | php -r 'echo trim(fgets(STDIN));'

      

Works fine, but when I create a process from nodejs:

spawner.js

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')]
})

      

stdin_test.php

<?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)));

      

Why is it php://stdin

empty? Is it safe to use /dev/stdin

? What is the difference between /dev/stdin

and php://stdin

?

Note that I also have this behavior between 2 node: process.stdin

empty but /dev/stdin

has the expected result.

+3


source to share


2 answers


I tested with the following script ( stdin_test.php

) using:

> echo test | php stdin_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);

      

I'm coming back:

STDIN :test
php://stdin :
/dev/stdin :

      

If I then comment out the line:



//echo trim(fgets(STDIN));

      

I'm coming back:

STDIN :
php://stdin :test
/dev/stdin :

      

If I comment out both of the first stdin echoes (and the file handler pointers), I get:

STDIN :
php://stdin :
/dev/stdin : test

      

A look at the documentation for php://input

and how it is one-off, if only (after 5.6) the "request body is saved", which is typical for POST requests, but not PUT requests (apparently). This makes me think they are called "streams" because you can walk in them once.

+2


source


Rewind your stdin stream in JS before PHP appears, otherwise the file pointer will sit at the end of what you just wrote.



0


source







All Articles