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.
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
"
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.
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);
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)