at
Unixシステムコマンドを使用してタスクを追加するときに、exec()
を使って出力をキャプチャしようと取り組んでいます。私の問題は、スクリプトから実行しても何も出力されないことですが、ターミナルから実行するとおよびPHP対話モードでは、数行が出力されます。
実行したいコマンドは次のとおりです。
_echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
_
var_dump()
はstring(0) ""
を与え、print_r()
はArray ()
を吐き出します。 NULL
を出力するShell_exec()
を使用してみましたが、Webページのコンテキストで実行すると次のようにhi
が出力されます。
_echo exec("echo 'hi'");
_
これも出力します:
_echo exec("atq");
_
ただし、at
を使用すると、何も出力されません。次の出力を取得するにはどうすればよいですか。
_exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
_
現在のところ、Apacheを介してPHP=で「通常」として実行しても何も出力されないため、ターミナルとPHPのインタラクティブコンソールでコマンドを実行すると、次のような結果が期待されます。
_php > echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
warning: commands will be executed using /bin/sh
job 1219 at Sun Jun 10 12:43:00 2012
_
_safe_mode
_がオフであり、at
またはexec()
を使用したその他のコマンドを実行すると、パイプラインエコーステートメントでatq
から出力が得られない理由を理解できません。私は この質問 を検索して読みましたが、まったく役に立ちませんでした。
at
からの出力を文字列またはexec()
で2番目の引数を使用している場合は配列に戻すには、exec()
をどのように取得できますか?
こんなに簡単なことだとは思いませんでした。必要なのは、実行するコマンドの最後に_2>&1
_を置いて、stderrをstdoutに再ルーティングすることだけです。これで、at
からの出力はすべてstdoutに出力されるため、exec()
によってキャプチャされます。
_echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);
_
私は1行または2行のソリューションを維持しようとしましたが、最終的に機能したのはproc_open()
を使用することだけでした。これは、at
がstderrにログを記録するためです。 、exec()
は読みません!これを指摘してくれた@Tourniquetに感謝しますが、彼は答えを削除しました。引用するには:
私が見る限り、execによってキャプチャされていないstderrへの出力で。私はそれにはあまり自信がありませんが、 http://php.net/manual/en/function.proc-open.php を使用することを検討してください。これにより、stderrを独自のパイプに転送できます。
これは実際には正しい方法です。私の解決策(stderrのみが必要なため)はこれを行うことでした:
_// Open process to run `at` command
$process = proc_open("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", array(2 => array("pipe", "w")), $pipes);
// Get stuff from stderr, because `at` prints out there for some odd reason
if(is_resource($process)) {
$output = stream_get_contents($pipes[2], 100);
fclose($pipes[2]);
$return_value = proc_close($process);
}
_
_$output
_には、stderrに出力されたat
がすべて含まれるようになり(エラーではないため、実際にはstdoutに移動する必要があります)、_$return_value
_には成功すると_0
_が含まれます。
ここでは、proc_openを使用したより複雑なソリューションを示します。私の場合、 '2>&1'の回避策が機能しないため、この回答を書いています。
function runCommand($bin, $command = '', $force = true)
{
$stream = null;
$bin .= $force ? ' 2>&1' : '';
$descriptorSpec = array
(
0 => array('pipe', 'r'),
1 => array('pipe', 'w')
);
$process = proc_open($bin, $descriptorSpec, $pipes);
if (is_resource($process))
{
fwrite($pipes[0], $command);
fclose($pipes[0]);
$stream = stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($process);
}
return $stream;
}
使用例:
// getting the mime type of a supplied file
echo runCommand('file -bi ' . escapeshellarg($file));
commandパラメーターを使用した別の例:
// executing php code on the fly
echo runCommand('/usr/bin/php', '<?php echo "hello world!"; ?>');
forceパラメーターを使用した別の例(これは、実行プロセス中に出力を変更するコマンドに役立ちます):
// converting an mp3 to a wav file
echo runCommand('lame --decode ' . escapeshellarg($source) . ' ' . escapeshellarg($dest), '', true);
これが役に立てば幸い:-)
最小限の(非)動作例を作成してみてください。すべてを分解し、一度に1つだけテストします。
これがあなたのbashの1つのエラーです:
hpek@melda:~/temp$ echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes
at: pluralization is wrong
job 22 at Sun Jun 10 14:48:00 2012
hpek@melda:~/temp$
Og minute
の代わりにminutes
と記述します。
at
からの出力は、メールで送信されます!!