PHPスクリプトを作成しようとしています。スクリプトは完成しましたが、設計されたプロセスを完了するのに10分ほどかかります。これは問題ではありませんが、ページをロードしたままにしておく必要があると思いますが、これは面倒です。プロセスを開始してから 10 分後に戻ってきて、生成されたログ ファイルを表示することはできますか?
10 に答える
「 ignore_user_abort (true)」を使用できます。
そのため、スクリプトは引き続き機能します (スクリプトの長さに注意してください。おそらく「set_time_limit (0)」を追加してください)。
ただし、ここで警告: 次の 2 行でスクリプトを停止することはできません。
ignore_user_abort(true);
set_time_limit(0);
ただし、サーバーに直接アクセスしてプロセスを強制終了することはできません。(そこにいて、無限ループを実行し、何度も何度も自分自身を呼び出し、サーバーを金切り声で停止させ、怒鳴られました...)
キューとキューを処理するための外部スクリプトが必要なようです。
たとえば、PHP スクリプトはエントリをデータベース テーブルに配置し、すぐに返す必要があります。次に、毎分実行される cron がキューをチェックし、各ジョブのプロセスを fork します。
ここでの利点は、Apache スレッドを 10 分間ロックしないことです。
Windowsでのこの種のプロセスには多くの問題がありました。私の状況は、「スクリプト」の応答を気にしなかったという点で少し異なりました。スクリプトを開始して、作業中に他のページ要求が通過できるようにしたかったのです。
何らかの理由で; 他のリクエストがハングするか、約60秒後にタイムアウトするという問題がありました(Apacheとphpの両方が約20分後にタイムアウトするように設定されていました)。とにかく、Firefox は 5 分後に (デフォルトで) タイムアウトすることが判明したため、それ以降は、Firefox の設定を変更しない限り、ブラウザーで何が起こっているのかを知ることができません。
次のように、プロセス オープン メソッドとプロセス クローズ メソッドを使用して、cli モードで php を開きました。
pclose(popen("start php myscript.php", "r"));
これは ( start を使用して) php プロセスを開き、開始プロセスを強制終了して、必要な時間だけ php を実行したままにします。手動でシャットダウンするには、プロセスを強制終了する必要があります。タイムアウトを設定する必要はなく、それを呼び出した現在のページを続行して、詳細を出力することができました。
これに関する唯一の問題は、スクリプトにデータを送信する必要がある場合は、別のソースを介して送信するか、「コマンド ライン」に沿ってパラメーターとして渡すことです。これはあまり安全ではありません。
ただし、必要なものはうまく機能し、スクリプトが常に開始され、中断することなく実行できるようになりました。
shell_exec コマンドが探しているものだと思います。
ただし、セーフモードでは無効になります。
それに関する PHP のマニュアル記事はこちら: http://php.net/shell_exec
ここにそれに関する記事があります: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
使用できる別のオプションがあり、スクリプト CLI を実行します...これはバックグラウンドで実行され、必要に応じて cronjob として実行することもできます。
例えば
> #!/usr/bin/php -q
<?php
//process logs
?>
これは cronjob としてセットアップでき、時間制限なしで実行されます....ただし、この例は UNIX ベースのオペレーティング システム用です。
参考までに、いくつかの処理を行う無限ループで実行されているphpスクリプトがあり、過去3か月間ノンストップで実行されています。
使用できますignore_user_abort()
- そうすれば、ブラウザを閉じたり、別のページに移動したりしても、スクリプトは引き続き実行されます。
ignore_user_abort(true);
bastiandoeen の回答に加えて、cUrl requestと組み合わせることができます。
要求の中止を偽装してCURLOPT_TIMEOUT_MS
、接続が閉じられた後も処理を続行します。
function async_curl($background_process=''){
//-------------get curl contents----------------
$ch = curl_init($background_process);
curl_setopt_array($ch, array(
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
CURLOPT_VERBOSE => 1,
CURLOPT_HEADER => 1
));
$out = curl_exec($ch);
//-------------parse curl contents----------------
//$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
//$header = substr($out, 0, $header_size);
//$body = substr($out, $header_size);
curl_close($ch);
return true;
}
async_curl('http://example.com/background_process_1.php');
注意
cURL を 1 秒未満でタイムアウトさせたい場合は、CURLOPT_TIMEOUT_MS を使用できますが、値が < 1000 ミリ秒でエラーが発生した場合に libcurl をすぐにタイムアウトさせるバグ/「機能」が「Unix ライクなシステム」にあります。 cURL エラー (28): タイムアウトに達しました". この動作の説明は次のとおりです。
[...]
解決策は、 CURLOPT_NOSIGNAL を使用してシグナルを無効にすることです
長所
- メソッドを切り替える必要はありません (互換性のある Windows & Linux)
- ヘッダーとバッファーを介した接続処理を実装する必要はありません (ブラウザーと PHP のバージョンに依存しません)。
短所
- カールエクステンションが必要
資力
ズク。
私はこれがうまくいくと確信しています:
<?php
pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]";
?>
「&」が重要です。プロセスが終了するのを待たないようにシェルに指示します。
また、このコードをphpで使用できます(「bastiandoeen」が言ったように)
ignore_user_abort(true);
set_time_limit(0);
サーバー停止コマンドで:
<?php
$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print $2}\' | xargs kill -9 ', $output);
echo "Server stopped. [OK]";
?>