web-dev-qa-db-ja.com

PHP Exec()後のStdErr

PHPでexec()を使用してコマンドを実行しています。成功するとURLが返されます。

$url = exec('report');

ただし、何か問題が発生した場合はstderrを確認したいと思います。ストリームをどのように読みますか? php:// stderrを使いたいのですが、使い方がわかりません。

50
martin

コマンドを実行してstderrstdoutの両方を取得し、「マージ」しない場合、ソリューションはおそらく proc_open を使用します。 stdin/stdout/stderrをパイプする方法を含め、実行中のコマンドを高度に制御します。

次に例を示します。stderrstdoutの両方に書き込むtest.shにこのシェルスクリプトがあるとしましょう。

#!/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;

では、PHPをtemp.phpでコーディングしましょう-まず、I/O記述子を初期化します。

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

次に、現在のディレクトリで、これらの記述子を使用してtest.shコマンドを実行し、I/Oがfrom/to $pipesである必要があることを伝えます。

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

これで、2つの出力パイプから読み取ることができます。

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

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

そして、これらの2つの変数の内容を出力する場合:

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

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

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

役立つかもしれない小さな機能:

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

必要に応じて、終了コードが返され、STDOUTとSTDERRが参照パラメーターになります。

39
mpen

マージされていない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);

Stdoutを無視してstderrのみを取得したい場合は、これを試すことができます。

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

execでこのようなことを行う簡単な方法は、終了コード(コマンドのステータス)を返すことです。

存在しないディレクトリを一覧表示しようとしていることに注意してください/non-dir/

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

出力

ls: '/ non-dir /'にアクセスできません:そのようなファイルまたはディレクトリはありません
int(2)

通常、UNIXベースのシステムでは、成功したステータスコードのほとんどは()なので、$retvalコマンドのステータスを確認します。

無効なパスのリストからエラーを却下するにはls: cannot access '/non-dir/': No such file or directorystderrをnullにリダイレクトできます

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

これは出力します:

int(2)

また、どのようなシナリオでもエラー文字列を使用する必要がある場合は、stderrstdoutにリダイレクトできます。

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

これは以下を出力します:

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