Shellスクリプトを呼び出す必要があるPHPスクリプトがありますが、出力はまったく気にしません。シェルスクリプトは多数のSOAP呼び出しを行い、完了するのに時間がかかるため、応答を待つ間、PHPリクエストを遅くしたくありません。実際、PHPリクエストは、シェルプロセスを終了せずに終了できるはずです。
私はさまざまなexec()
、Shell_exec()
、pcntl_fork()
などの関数を調べましたが、どれも私が望むものを正確に提供していないようです。 (または、もしそうなら、それは私には明確ではありません。)提案はありますか?
「出力を気にしない」場合、スクリプトのexecを&
で呼び出してプロセスをバックグラウンドにできませんでしたか?
EDIT-この投稿にコメントされた@ AdamTheHut を組み込むと、これをexec
の呼び出しに追加できます。
" > /dev/null 2>/dev/null &"
これにより、stdio
(最初の>
)とstderr
(2>
)の両方が/dev/null
にリダイレクトされ、バックグラウンドで実行されます。
同じことを行う方法は他にもありますが、これが最も読みやすい方法です。
上記の二重リダイレクトの代替:
" &> /dev/null &"
実際には独立したプロセスを開始しているため、このためにatを使用しました。
<?php
`echo "the command"|at now`;
?>
すべてのWindowsユーザーへ:非同期PHPスクリプトを実行する良い方法を見つけました(実際、ほとんどすべてで動作します)。
これは、popen()およびpclose()コマンドに基づいています。そして、WindowsとUnixの両方でうまく機能します。
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
Linuxでは、次のことができます。
$cmd = 'Nohup Nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = Shell_exec($cmd);
これにより、コマンドプロンプトでコマンドが実行され、PIDが返されるだけです。PIDで> 0をチェックし、機能することを確認できます。
この質問は似ています: PHPにはスレッドがありますか?
php-execute-a-background-process にはいくつかの良い提案があります。私はかなり良いと思うが、私は偏っている:)
Linuxでは、コマンドの最後にアンパサンドを追加することにより、新しい独立したスレッドでプロセスを開始できます
mycommand -someparam somevalue &
Windowsでは、DOSコマンド「開始」を使用できます
start mycommand -someparam somevalue
それを行う正しい方法(!)は
fork forks、setsidは現在のプロセスにマスタープロセス(親なし)になるように指示し、execveは呼び出しプロセスに呼び出されるプロセスに置き換えるように指示します。親が子に影響を与えることなく終了できるように。
$pid=pcntl_fork();
if($pid==0)
{
posix_setsid();
pcntl_exec($cmd,$args,$_ENV);
// child becomes the standalone detached process
}
// parent's stuff
exit();
私はこれを使用しました...
/**
* Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.
* Relies on the PHP_PATH config constant.
*
* @param string $filename file to execute
* @param string $options (optional) arguments to pass to file via the command line
*/
function asyncInclude($filename, $options = '') {
exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}
(PHP_PATH
はdefine('PHP_PATH', '/opt/bin/php5')
などのように定義されたconstです)
コマンドラインを介して引数を渡します。 PHPでそれらを読むには、 argv を参照してください。
また、 Symfony Process Component がこれに役立つこともわかりました。
use Symfony\Component\Process\Process;
$process = new Process('ls -lsa');
// ... run process in background
$process->start();
// ... do other things
// ... if you need to wait
$process->wait();
// ... do things after the process has finished
GitHub repo でどのように機能するかを確認してください。
私にとって本当に役立つことがわかった唯一の方法は次のとおりです。
Shell_exec('./myscript.php | at now & disown')
PHPスクリプトをdaemonまたはcronjobとして実行することもできます:#!/usr/bin/php -q
名前付きfifoを使用します。
#!/bin/sh
mkfifo trigger
while true; do
read < trigger
long_running_task
done
その後、長時間実行されるタスクを開始したいときはいつでも、単純に改行(トリガーファイルへの非ブロッキング)を書き込みます。
入力がPIPE_BUF
より小さく、単一のwrite()
操作である限り、引数をfifoに書き込み、スクリプトで$REPLY
として表示させることができます。
キューを使用せずに、次のように proc_open()
を使用できます。
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w") //here curaengine log all the info into stderror
);
$command = 'ping stackoverflow.com';
$process = proc_open($command, $descriptorspec, $pipes);