PHP StdErr после Exec()
В PHP я выполняю команду с exec(), и она возвращает в случае успешного URL-адреса;
$url = exec('report');
Однако, я хочу проверить stderr, если что-то пошло не так. Как бы я прочитал поток?
Я хочу использовать php://stderr, но я не уверен, как его использовать.
Ответы
Ответ 1
Если вы хотите выполнить команду и получить как stderr
и stdout
, а не "объединенные", решение, вероятно, будет использовать proc_open
, который обеспечивает высокий уровень контроля над выполняемой командой, включая способ stdin
/stdout
/стандартный stderr
И вот пример: давайте рассмотрим, что у нас есть этот shell-скрипт в 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;
Теперь давайте temp.php
некоторый PHP в temp.php
- сначала мы инициализируем дескрипторы temp.php
:
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w"), // stderr
);
И затем выполните команду test.sh
, используя эти дескрипторы, в текущем каталоге и сказав, что 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
"
Ответ 2
Небольшая функция, которая может быть полезна:
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 являются ссылочными параметрами, если они вам нужны.
Ответ 3
Другой способ получить 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);
Ответ 4
Короткий способ сделать это с помощью exec
- вернуть код завершения (состояние команды).
Обратите внимание, что я пытаюсь перечислить несуществующий каталог /non-dir/
exec('ls /non-dir/', $out, $retval);
var_dump($retval);
Выход
ls: не может получить доступ к '/non-dir/': нет такого файла или каталога
Int (2)
Обычно в Unix-системах большинство успешных кодов статусов равно (0), поэтому вы можете проверить свой $retval
чтобы узнать статус команды.
отклонить ошибку из списка неверного пути ls: cannot access '/non-dir/': No such file or directory
вы можете перенаправить ваш stderr на ноль
exec('ls /non-dir/ 2>/dev/null', $out, $retval);
var_dump($retval);
это выведет:
Int (2)
также, если вам нужна строка ошибки, чтобы использовать ее в любом сценарии, вы можете перенаправить ваш stderr на стандартный вывод.
exec('ls /non-dir/ 2>&1', $out, $retval);
print_r($out);
var_dump($retval);
это выведет следующее:
Array
(
[0] => ls: cannot access '/non-dir/': No such file or directory
)
int(2)