Как получить выход из процесса opend по popen в php?

файл a.php:

<?php
echo "abcdef";
?>

файл b.php:

<?php
$h=popen('php a.php',r);
pclose($h);
?>

Вопрос:

Я не вижу результат эха на консоли; почему и как это увидеть?

Я не хочу делать это в файле b.php вроде: echo stream_get_contents($h);

Ответ 1

Проверьте второй пример в документации popen, он точно показывает, как это сделать:

<?php
error_reporting(E_ALL);

/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);

Этот фрагмент читается из stderr. Удалите трубу для чтения из стандартного вывода.

Ответ 2

Вы не можете увидеть результат эха на консоли, потому что он никогда не попадал на консоль. Открыв процесс в режиме чтения, его STDOUT был связан с дескриптором файла открытого процесса. Единственный способ получить выход на консоль был бы, если бы вы прочитали из этого дескриптора файла, а затем повторили его.

Поток, другими словами, таков.

  • b.php начинает работать - его STDIN и STDOPUT связаны с вашей консолью как обычно
  • он вызывает popen в режиме чтения и сохраняет ресурс потока в $h
  • это приводит к запуску a.php, причем его STDOUT связан с файловым дескриптором в $h, а его STDIN не привязан к чему-либо
  • это означает, что, как видите, a.php не имеет прямого доступа к консоли, с которой был запущен b.php.
  • a.php записывает свой вывод в этот поток, а затем заканчивает выполнение
  • b.php никогда ничего не делает с потоком в $h, он просто закрывает его, поэтому вывод a.php теряется.

Надеюсь, что это объясняет, что здесь происходит. Если вы хотите увидеть вывод a.php на консоли, тогда b.php нужно прочитать его из потока в $h, а затем повторить его, так как только b.php имеет доступ к консоли.

В качестве альтернативы, если вы используете system() вместо popen(), вывод будет выводиться в вызывающей консоли script автоматически, так как использование system() передает основную script STDIN и STOUT в программу или script, который вы вызываете.

Ответ 3

попробуйте это:

while (@ ob_end_flush()); // end all output buffers if any
$proc = popen('/path/to/executable 2>&1', 'r');
while (!feof($proc))
{
    echo fread($proc, 4096);
    @ flush();
}