web-dev-qa-db-fra.com

PHP StdErr après Exec ()

Dans PHP j'exécute une commande avec exec (), et elle retourne en cas de succès une URL;

$url = exec('report');

Cependant, je veux vérifier stderr, si quelque chose s'est mal passé. Comment lire le flux? Je veux utiliser php: // stderr, mais je ne sais pas comment l'utiliser.

50
martin

Si vous souhaitez exécuter une commande et obtenir à la fois stderr et stdout, et non "fusionnées", une solution consisterait probablement à utiliser proc_open , qui offre un excellent niveau de contrôle sur la commande en cours d'exécution - y compris un moyen de diriger stdin/stdout/stderr.

Et voici un exemple: considérons que nous avons ce Shell-script, dans test.sh, qui écrit à la fois dans stderr et 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;

Maintenant, codons du PHP, dans temp.php - tout d'abord, nous initialisons les descripteurs d'E/S:

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

Et puis, exécutez le test.sh, en utilisant ces descripteurs, dans le répertoire courant, et en disant que les E/S doivent être de/vers $pipes:

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

Nous pouvons maintenant lire les deux tubes de sortie:

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

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

Et, si nous sortons le contenu de ces deux variables:

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

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

Nous obtenons la sortie suivante lors de l'exécution de temp.php script:

$ 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
"
71
Pascal MARTIN

Une petite fonction qui pourrait être 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);
}

Le code de sortie est renvoyé et STDOUT et STDERR sont des paramètres de référence si vous en avez besoin.

39
mpen

Une autre façon d'obtenir stdout/stderr non fusionné.

$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 vous voulez ignorer stdout et obtenir uniquement stderr, vous pouvez essayer ceci:

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

La façon courte de faire une telle chose avec exec est de retourner le code de sortie (état de la commande)

Notez que j'essaie de répertorier un répertoire inexistant /non-dir/

exec('ls /non-dir/', $out, $retval);
var_dump($retval);

Production

ls: impossible d'accéder à '/ non-dir /': Aucun fichier ou répertoire de ce type
int (2)

Normalement, dans un système basé sur Unix, la plupart des codes d'état réussis sont () afin que vous puissiez vérifier votre $retval pour connaître l'état de la commande.

pour empêcher l'erreur de répertorier un chemin non valide ls: cannot access '/non-dir/': No such file or directory vous pouvez rediriger votre stderr vers null

exec('ls /non-dir/ 2>/dev/null', $out, $retval);
var_dump($retval);

cela produira:

int (2)

aussi, si vous avez besoin de la chaîne d'erreur pour l'utiliser dans n'importe quel scénario, vous pouvez rediriger votre stderr vers stdout.

exec('ls /non-dir/ 2>&1', $out, $retval);
print_r($out);
var_dump($retval);

cela produira les éléments suivants:

Array
(
    [0] => ls: cannot access '/non-dir/': No such file or directory
)
int(2)
0
hassan