Esto es lo que intenté hacer yo mismo:
$ type 1.sh
#!/bin/bash -eu
php -r 'var_dump(file_get_contents($_SERVER["argv"][1]));' -- <(echo 1)
$ ./1.sh
PHP Warning: file_get_contents(/dev/fd/63): failed to open stream: No such file or directory in Command line code on line 1
Warning: file_get_contents(/dev/fd/63): failed to open stream: No such file or directory in Command line code on line 1
bool(false)
Lo probé en Debian 6
( php-5.4.14
, bash-4.1.5
) y Arch Linux
( php-5.4.12
, bash-4.2.42
).
UPD
$ strace -f -e trace=file php -r 'var_dump(file_get_contents($_SERVER["argv"][1]));' -- <(echo 1)
...
open("/usr/lib/php5/20100525/mongo.so", O_RDONLY) = 3
lstat("/dev/fd/63", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0
readlink("/dev/fd/63", "pipe:[405116]"..., 4096) = 13
lstat("/dev/fd/pipe:[405116]", 0x7fff5ea44850) = -1 ENOENT (No such file or directory)
lstat("/dev/fd", {st_mode=S_IFLNK|0777, st_size=13, ...}) = 0
readlink("/dev/fd", "/proc/self/fd"..., 4096) = 13
lstat("/proc/self/fd", {st_mode=S_IFDIR|0500, st_size=0, ...}) = 0
lstat("/proc/self", {st_mode=S_IFLNK|0777, st_size=64, ...}) = 0
readlink("/proc/self", "31536"..., 4096) = 5
lstat("/proc/31536", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
lstat("/proc", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/31536/fd/pipe:[405116]", O_RDONLY) = -1 ENOENT (No such file or directory)
PHP Warning: file_get_contents(/dev/fd/63): failed to open stream: No such file or directory in Command line code on line 1
Warning: file_get_contents(/dev/fd/63): failed to open stream: No such file or directory in Command line code on line 1
bool(false)
$ strace -f -e trace=file php <(echo 12)
...
open("/usr/lib/php5/20100525/mongo.so", O_RDONLY) = 3
open("/dev/fd/63", O_RDONLY) = 3
lstat("/dev/fd/63", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0
readlink("/dev/fd/63", "pipe:[413359]", 4096) = 13
lstat("/dev/fd/pipe:[413359]", 0x7fffa69c3c00) = -1 ENOENT (No such file or directory)
lstat("/dev/fd/63", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0
readlink("/dev/fd/63", "pipe:[413359]", 4096) = 13
lstat("/dev/fd/pipe:[413359]", 0x7fffa69c19b0) = -1 ENOENT (No such file or directory)
lstat("/dev/fd", {st_mode=S_IFLNK|0777, st_size=13, ...}) = 0
readlink("/dev/fd", "/proc/self/fd"..., 4096) = 13
lstat("/proc/self/fd", {st_mode=S_IFDIR|0500, st_size=0, ...}) = 0
lstat("/proc/self", {st_mode=S_IFLNK|0777, st_size=64, ...}) = 0
readlink("/proc/self", "32214"..., 4096) = 5
lstat("/proc/32214", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
lstat("/proc", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
2
Respuesta1
El problema es que quieres que php lea la entrada de un descriptor de archivo, pero lo obligas a leer como un archivo normal.
Primero, prueba esto:
$ echo <(ls)
/dev/fd/63
entonces puedes procesar ls
la salida leyendo /dev/fd/63
. La sustitución del proceso devolverá el archivo file descriptor
, que otro comando utiliza para leer su salida.
En su caso, usa $_SERVER["argv"][1]
, lo que significa que php se interpretará así:
file_get_contents(/dev/fd/63)
Desde el manual de php, puedes ver el prototipo de file_get_contents
la función:
string file_get_contents ( string $filename [, bool $use_include_path =
false [, resource $context [, int $offset = -1 [, int $maxlen ]]]] )
Ops, php se considerará /dev/fd/63
un archivo normal aquí, pero en realidad es un archivo file descriptor
.
Para acceder al descriptor de archivo, debe utilizar php://fd
, php://fd/63
accederá al contenido del descriptor de archivo 63:
$ php -r 'var_dump(file_get_contents("php://".substr($_SERVER["argv"][1],-5)));' -- <(echo test.txt)
string(9) "test.txt
"
Puedes ver que ahora PHP puede procesar contenido en formato /dev/fd/63
. Pero nuestro propósito es leer el contenido del archivo, que se proporciona mediante sustitución de procesos (en mi ejemplo, es test.txt
). No sé mucho sobre php, así que agrego otro file_get_contents
:
$ php -r 'var_dump(file_get_contents(file_get_contents("php://".substr($_SERVER["argv"][1],-5))));' -- <(echo -n test.txt)
string(13) "Hello world!
"
Utilizo echo -n
para eliminar la nueva línea de la salida de eco; de lo contrario, php verá la salida "test.txt\n".
Nota
Para obtener más información sobre cómo acceder al descriptor de archivos en php, puede veraquí.
Respuesta2
Este es el problema:
readlink("/dev/fd/63", "pipe:[405116]"..., 4096) = 13
lstat("/dev/fd/pipe:[405116]", 0x7fff5ea44850) = -1 ENOENT
Sin ninguna buena razón (en mi humilde opinión), php
intenta obtener el nombre real del destino del enlace. Lamentablemente, el destino del enlace no forma parte del sistema de archivos, por lo que el intento de acceder a ese nombre falla y provoca este error. El enlace simbólico sólo se puede abrir como tal. Considero que esto es un error en php
. Podrías usar un FIFO en su lugar:
mkfifo /my/fifo; output_cmd >/my/fifo & php -r ... /my/fifo
Respuesta3
Esta es una vieja pregunta, pero acabo de descubrir la respuesta, así que pensé en compartirla. Quizás ayude a alguien.
En su lugar , puede utilizar el php://
contenedor de secuencia para abrir el descriptor de archivo:
$fd = $argv[1];
$handle = fopen(str_replace('/dev/','php://',$fd));
Entonces, en lugar de abrir el /dev/fd/[nn]
descriptor de archivo proporcionado por el sistema operativo. Estarás abriendo php://fd/[nn]
lo que funcionará. No estoy seguro de por qué falla la apertura del descriptor de archivo en algunos sistemas pero no en otros.
Este fue unviejo errory se suponía que había sido arreglado.
Respuesta4
Esto es lo que terminé usando...
php -r "var_dump(file_get_contents('php://stdin'));" < <(echo this is a win)
Si estás intentando hacer otras cosas con stdin, esto obviamente no funcionará para ti, y esto no es diferente de
php -r "var_dump(stream_get_contents(STDIN));" < <(echo this is a win)
lo que me lleva a preguntarme qué es lo que realmente intentabas hacer y por qué estás atascado en file_get_contents. :)
Referencia -http://php.net/manual/en/wrappers.php.php