2010-02-23 25 views
43

En PHP estoy ejecutando un comando con exec(), y devuelve si tiene éxito una URL;PHP StdErr after Exec()

$url = exec('report'); 

Sin embargo, quiero comprobar stderr, si algo ha ido mal. ¿Cómo leería la transmisión? Quiero usar php: // stderr, pero no estoy seguro de cómo usarlo.

+0

Le recomendaré que use el componente Symfony/Process. –

Respuesta

65

Si desea ejecutar un comando, y obtener tanto stderr y stdout, no se "fusionaron", una solución, probablemente a utilizar proc_open, que proporciona un gran nivel de control sobre el comando que está siendo ejecutado - incluyendo un modo a la tubería stdin/stdout/stderr.


Y aquí es un ejemplo: Vamos a considerar tenemos este script de shell, en test.sh, que escribe a la vez stderr y 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; 


Ahora, vamos código algo de PHP, en temp.php - en primer lugar, inicializamos las E/S descriptores:

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


Y, a continuación, ejecutar el comando test.sh, utilizando los descriptores, en el directorio actual, y diciendo que la E/S debe ser desde/hasta $pipes:

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


Ahora podemos leer de los dos tubos de salida :

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

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


Y, si la salida del contenido de esas dos variables:

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

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


obtenemos el siguiente resultado cuando se ejecuta la secuencia de comandos 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 
" 


Esperanza esto ayuda :-)

+3

Al usar esto, asegúrese de que todos usen proc_close cuando todo haya terminado por limpieza. –

+0

¿Por qué se redirige el resultado en un proceso var? –

+3

@BriceFavre Lo pone en un proceso var para que pueda cerrarlo más tarde con proc_close, que también devolverá el código de retorno con el que salió el proceso. '$ returnCode = proc_close ($ process);' –

6

Otra manera de conseguir sin combinar 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); 

Si desea ignorar la salida estándar y obtener sólo stderr, puede intentar esto:

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

Una pequeña función que podría ser útil:

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

Se devuelve el código de salida y STDOUT y STDERR son parámetros de referencia si los necesita.

+2

Agradable y simple, funciona a la perfección. ¡¡¡Gracias por publicar!!! –

Cuestiones relacionadas