Domanda PHP StdErr dopo Exec ()


In PHP sto eseguendo un comando con exec (), e restituisce se ha successo un URL;

$url = exec('report');

Tuttavia, voglio controllare lo stderr, se qualcosa è andato storto. Come leggerei il flusso? Voglio usare php: // stderr, ma non sono sicuro di come usarlo.


44
2018-02-23 18:13


origine


risposte:


Se si desidera eseguire un comando e ottenere entrambi stderr e stdout, non "unito", probabilmente una soluzione da usare proc_open, che fornisce un ottimo livello di controllo sul comando che viene eseguito, incluso un modo per pipe stdin/stdout/stderr.


Ed ecco un esempio: consideriamo di avere questo script di shell, in test.sh, che scrive su entrambi stderr e 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;


Ora, codifichiamo alcuni PHP, in temp.php - Innanzitutto, inizializziamo i descrittori di I / O:

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


E, quindi, esegui il test.sh comando, usando quei descrittori, nella directory corrente e dicendo che l'I / O dovrebbe essere da / a $pipes :

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


Ora possiamo leggere dai due tubi di uscita:

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

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


E, se produciamo il contenuto di queste due variabili:

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

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


Otteniamo il seguente risultato durante l'esecuzione di temp.php sceneggiatura:

$ 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
"


Spero che questo ti aiuti :-)


67
2018-02-23 18:50



Una piccola funzione che potrebbe essere utile:

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

Il codice di uscita viene restituito e STDOUT e STDERR sono parametri di riferimento se ne hai bisogno.


32
2017-09-16 23:28



Un altro modo per ottenere stdout / stderr non raggruppati.

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

Se vuoi ignorare lo stdout e ottenere solo stderr, puoi provare questo:

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

6
2017-11-22 13:17