2010-02-23 16 views
43

W PHP wykonuję polecenie z exec(), i zwraca po pomyślnym adresie URL;PHP StdErr po Exec()

$url = exec('report'); 

Jednak chcę sprawdzić stderr, jeśli coś poszło nie tak. Jak czytałem strumień? Chcę użyć php: // stderr, ale nie jestem pewien, jak z niego korzystać.

+0

Zalecam korzystanie z komponentu Symfony/Process. –

Odpowiedz

65

Jeśli chcesz wykonać polecenie i uzyskać zarówno stderr i stdout, a nie „połączone”, rozwiązanie byłoby prawdopodobnie używać proc_open, która zapewnia dużą poziom kontroli nad poleceniem że to jest wykonywane - w tym sposób do rury stdin/stdout/stderr.


A oto przykład: rozważmy mamy ten skrypt powłoki, w test.sh, który pisze zarówno stderr i 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; 


Teraz Kod trochę PHP, w temp.php - po pierwsze, że inicjalizacja deskryptorów I/o:

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


A zatem wykonać polecenie z test.sh, stosując te wskaźniki, w bieżącym katalogu, a mówiąc I/O powinny być z/do $pipes:

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


Teraz możemy odczytać z dwóch rur wyjściowych :

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

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


A jeśli mamy wyjście treść tych dwóch zmiennych:

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

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


Otrzymujemy następujący wynik podczas wykonywania skryptu 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 
" 


Nadzieja to pomaga :-)

+3

Używając tego, upewnij się, że używasz proc_close, kiedy skończysz wszystko dla czystej czystości. –

+0

Dlaczego przekierowujesz wynik do procesu var? –

+3

@BriceFavre Umieszcza go w procesie var, dzięki czemu może go zamknąć później proc_close, który również zwróci kod powrotu, z którego proces zakończył się. '$ returnCode = proc_close ($ process);' –

6

Innym sposobem uzyskania stdout/stderr niezłączonych.

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

Jeśli chcesz ignorować stdout i dostać tylko stderr, można spróbować to:

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

Trochę funkcji, które mogą być pomocne:

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); 
} 

zwracany jest kod wyjścia a STDOUT i STDERR są paramaturami odniesienia, jeśli ich potrzebujesz.

+2

Ładne i proste, działa idealnie. Dzięki za publikację !!! –