Как открыть файл с заменой процесса из php?

Вот что я пытался сделать сам:

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

Я тестировал его на Debian 6 ( php-5.4.14 , bash-4.1.5 ) и 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 

Проблема в том, что вы хотите, чтобы php читал ввод из дескриптора файла, но вы заставляете его читать как обычный файл.

Сначала попробуйте следующее:

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

то вы можете обрабатывать ls путем чтения /dev/fd/63 . Подстановка процесса вернет file descriptor , который используется другой командой для чтения его вывода.

В вашем случае вы используете $_SERVER["argv"][1] , что означает, что php будет интерпретировать следующим образом:

 file_get_contents(/dev/fd/63) 

Из руководства php вы можете увидеть protorype функции file_get_contents :

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

Ops, php рассмотрит /dev/fd/63 как обычный файл здесь, но это действительно file descriptor .

Чтобы получить доступ к файловому дескриптору, вы должны использовать php://fd , php://fd/63 будет обращаться к содержимому файлового дескриптора 63:

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

Вы можете видеть, теперь php может обрабатывать контент в /dev/fd/63 . Но наша цель – чтение содержимого файла, которое обеспечивается посредством замены процесса (в моем примере это test.txt ). Я не знаю много о php, поэтому я добавляю еще один 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! " 

Я использую echo -n для удаления новой строки из echo ouput, иначе php увидит вывод «test.txt \ n».

Заметка

Дополнительные сведения о доступе к файловому дескриптору в php см. Здесь .

Это проблема:

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

Без уважительной причины (IMHO) php пытается получить реальное имя целевой ссылки. К сожалению, цель ссылки не является частью файловой системы, поэтому попытка получить доступ к этому имени не удалась и вызывает эту ошибку. Символьную ссылку можно открыть только как таковую. Я считаю это ошибкой в php . Вместо этого вы можете использовать FIFO:

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

Вот что я в итоге использовал …

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

Если вы пытаетесь сделать другие вещи с помощью stdin, это явно не сработает для вас, и это ничем не отличается от

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

что заставляет меня задаться вопросом, что именно вы на самом деле пытаетесь сделать, и почему вы застряли на file_get_contents? 🙂

Ссылка – http://php.net/manual/en/wrappers.php.php