В PHP я выполняю команду с exec (), и она возвращает в случае успешного URL-адреса;
$url = exec('report');
Тем не менее, я хочу проверить stderr, если что-то пошло не так. Как бы я прочитал поток? Я хочу использовать php: // stderr, но я не уверен, как его использовать.
Если вы хотите выполнить команду и получить как 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
, что i / o должен быть от / до $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 "
Надеюсь это поможет 🙂
Небольшая функция, которая может быть полезна:
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 являются ссылочными параметрами, если они вам понадобятся.
Другой способ получить 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);