PHP StdErr после Exec () - PullRequest
       37

PHP StdErr после Exec ()

46 голосов
/ 23 февраля 2010

В PHP я выполняю команду с exec (), и в случае успеха возвращается URL;

$url = exec('report');

Однако я хочу проверить stderr, если что-то пошло не так. Как бы я прочитал поток? Я хочу использовать php: // stderr, но я не уверен, как его использовать.

Ответы [ 3 ]

68 голосов
/ 23 февраля 2010

Если вы хотите выполнить команду и получить и stderr, и stdout, а не "объединенные", решение, вероятно, будет использовать proc_open, что обеспечивает высокий уровень контроля над выполняемой командой, включая способ передачи stdin / stdout / stderr.

И вот пример: давайте рассмотрим, что у нас есть этот скрипт-сценарий, в test.sh, который записывает и в stderr, и в stdout:

#!/bin/bash

echo 'this is on stdout';
echo 'this is on stdout too';

echo 'this is on stderr' >&2;
echo 'this is on stderr too' >&2;

Теперь давайте кодируем некоторый PHP на temp.php - сначала мы инициализируем дескрипторы ввода / вывода:

$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin
   1 => array("pipe", "w"),  // stdout
   2 => array("pipe", "w"),  // stderr
);

И затем выполните команду test.sh, используя эти дескрипторы, в текущем каталоге и заявив, что ввод / вывод должен быть от / до $pipes:

$process = proc_open('./test.sh', $descriptorspec, $pipes, dirname(__FILE__), null);

Теперь мы можем читать из двух выходных каналов:

$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);

$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);

И, если мы выведем содержимое этих двух переменных:

echo "stdout : \n";
var_dump($stdout);

echo "stderr :\n";
var_dump($stderr);

При выполнении сценария temp.php мы получаем следующий вывод:

$ php ./temp.php
stdout :
string(40) "this is on stdout
this is on stdout too
"
stderr :
string(40) "this is on stderr
this is on stderr too
"
36 голосов
/ 17 сентября 2014

Небольшая функция, которая может быть полезна:

function my_shell_exec($cmd, &$stdout=null, &$stderr=null) {
    $proc = proc_open($cmd,[
        1 => ['pipe','w'],
        2 => ['pipe','w'],
    ],$pipes);
    $stdout = stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $stderr = stream_get_contents($pipes[2]);
    fclose($pipes[2]);
    return proc_close($proc);
}

Код выхода возвращается, и STDOUT и STDERR являются ссылочными параметрами, если они вам нужны.

6 голосов
/ 22 ноября 2012

Еще один способ получить unmerged stdout / stderr.

$pp_name = "/tmp/pp_test";
@unlink($pp_name);
posix_mkfifo($pp_name, 0777);
$pp = fopen($pp_name, "r+");
stream_set_blocking($pp, FALSE);
exec("wget -O - http://www.youtube.com 2>$pp_name", $r_stdout);
$r_stderr = stream_get_contents($pp);
var_dump($r_stderr);
fclose($pp);
unlink($pp_name);

Если вы хотите игнорировать stdout и получить только stderr, вы можете попробовать это:

exec("wget -O - http://www.youtube.com 2>&1 >/dev/null", $r_stderr);
...