Wie öffnet man eine prozessersetzte Datei in PHP?

Wie öffnet man eine prozessersetzte Datei in PHP?

Folgendes habe ich selbst versucht:

$ 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)

Ich habe es an Debian 6( php-5.4.14, bash-4.1.5) und Arch Linux( php-5.4.12, bash-4.2.42) getestet.

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

Antwort1

Das Problem besteht darin, dass Sie möchten, dass PHP die Eingabe aus einem Dateideskriptor liest, Sie es aber zwingen, sie wie eine normale Datei zu lesen.

Versuchen Sie zunächst Folgendes:

$ echo <(ls)
/dev/fd/63

lsAnschließend können Sie die Ausgabe durch Lesen verarbeiten /dev/fd/63. Die Prozessersetzung gibt das zurück file descriptor, das von anderen Befehlen zum Lesen ihrer Ausgabe verwendet wird.

In Ihrem Fall verwenden Sie $_SERVER["argv"][1], was bedeutet, dass PHP es wie folgt interpretiert:

file_get_contents(/dev/fd/63)

Im PHP-Handbuch können Sie das file_get_contentsFunktionsprototyp sehen:

string file_get_contents ( string $filename [, bool $use_include_path =
false [, resource $context [, int $offset = -1 [, int $maxlen ]]]] )

Ups, PHP wird hier als normale Datei betrachtet /dev/fd/63, aber es ist wirklich eine file descriptor.

Um auf den Dateideskriptor zuzugreifen, müssen Sie verwenden php://fd. php://fd/63Dadurch wird auf den Inhalt des Dateideskriptors 63 zugegriffen:

$ php -r 'var_dump(file_get_contents("php://".substr($_SERVER["argv"][1],-5)));' -- <(echo test.txt)
string(9) "test.txt
"

Sie können sehen, dass PHP jetzt Inhalte in verarbeiten kann /dev/fd/63. Unser Ziel ist jedoch das Lesen von Dateiinhalten, die über Prozesssubstitution bereitgestellt werden (in meinem Beispiel ist es test.txt). Ich weiß nicht viel über PHP, also füge ich noch ein weiteres hinzu 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!
"

Ich echo -nentferne immer die neue Zeile aus der Echo-Ausgabe, sonst sieht PHP die Ausgabe „test.txt\n“.

Notiz

Weitere Informationen zum Zugriff auf Dateideskriptoren in PHP finden Sie unterHier.

Antwort2

Das ist das Problem:

readlink("/dev/fd/63", "pipe:[405116]"..., 4096) = 13
lstat("/dev/fd/pipe:[405116]", 0x7fff5ea44850) = -1 ENOENT

Versucht ohne triftigen Grund (meiner Meinung nach) phpden echten Namen des Linkziels zu ermitteln. Leider ist das Linkziel nicht Teil des Dateisystems, daher schlägt der Versuch, auf diesen Namen zuzugreifen, fehl und verursacht diesen Fehler. Der Symlink kann nur als solcher geöffnet werden. Ich halte das für einen Fehler in php. Sie könnten stattdessen ein FIFO verwenden:

mkfifo /my/fifo; output_cmd >/my/fifo & php -r ... /my/fifo

Antwort3

Dies ist eine alte Frage, aber ich habe gerade die Antwort herausgefunden und dachte, ich teile sie mit Ihnen. Vielleicht hilft sie jemandem.

Sie können stattdessen den Stream-Wrapper verwenden php://, um den Dateideskriptor zu öffnen:

 $fd = $argv[1];
 $handle = fopen(str_replace('/dev/','php://',$fd)); 

Anstatt also den /dev/fd/[nn]vom Betriebssystem bereitgestellten Dateideskriptor zu öffnen, öffnen Sie Folgendes, php://fd/[nn]was funktioniert. Ich bin nicht sicher, warum das Öffnen des Dateideskriptors auf einigen Systemen fehlschlägt, auf anderen jedoch nicht.

Das war einalter Fehlerund sollte behoben sein.

Antwort4

Das habe ich letztendlich verwendet ...

php -r "var_dump(file_get_contents('php://stdin'));" < <(echo this is a win)

Wenn Sie versuchen, andere Dinge mit stdin zu tun, wird dies offensichtlich nicht für Sie funktionieren, und das ist nicht anders als

php -r "var_dump(stream_get_contents(STDIN));" < <(echo this is a win)

was mich zu der Frage führt, was Sie eigentlich versucht haben und warum Sie bei file_get_contents hängen bleiben? :)

Referenz -http://php.net/manual/en/wrappers.php.php

verwandte Informationen