質問
PHPスクリプトを作成しようとしています。スクリプトは終了していますが、設計されたプロセスを完了するのに10分ほどかかります。これは問題ではありませんが、この間ずっとページをロードし続ける必要があると思いますが、これは迷惑です。プロセスを開始してから10分後に戻って、生成されたログファイルを表示するだけでいいですか?
解決
まあ、<!> quot; ignore_user_abort (true)<!> quot;
したがって、スクリプトは引き続き機能します(スクリプトの継続時間に注意してください。おそらく<!> quot; set_time_limit (0)<!> quot;)
ただし、ここで警告:次の2行でスクリプトを停止することはできません:
ignore_user_abort(true);
set_time_limit(0);
サーバーに直接アクセスし、そこでプロセスを強制終了できる場合を除きます! (そこに来て、無限ループを繰り返し、何度も何度も自分自身を呼び出し、サーバーを金切り声で止め、叫びました...)
他のヒント
キューとキューを処理するための外部スクリプトが必要なようです。
たとえば、PHPスクリプトはデータベーステーブルにエントリを配置し、すぐに戻る必要があります。次に、毎分実行されるcronがキューをチェックし、各ジョブのプロセスをフォークします。
ここでの利点は、Apacheスレッドを10分間ロックアップしないことです。
Windowsでこの種のプロセスに多くの問題がありました。 <!> quot; script <!> quot;の応答を気にしないという点で、私の状況は少し異なっていました-スクリプトを開始し、仕事で忙しいときに他のページリクエストが通過できるようにしました。
何らかの理由で。私は、他のリクエストをハングさせるか、約60秒後にタイムアウトする(apacheとphpの両方が約20分後にタイムアウトするように設定されている)ことに問題がありました。また、Firefoxは5分後に(デフォルトで)タイムアウトするため、その時点以降は、Firefoxの設定を変更しないと、ブラウザーで何が起こっているのかわかりません。
次のように、CLIモードでPHPを開くために、プロセスのopenメソッドとプロセスのcloseメソッドを使用することになりました。
pclose(popen("start php myscript.php", "r"));
これは、(startを使用して)phpプロセスを開き、開始プロセスを強制終了しますが、phpを必要な時間だけ実行します-再びプロセスを強制終了して手動でシャットダウンする必要があります。タイムアウトを設定する必要はなく、それを呼び出した現在のページを継続させ、詳細を出力することができます。
これに関する唯一の問題は、スクリプトにデータを送信する必要がある場合、別のソース経由で送信するか、<!> quot;コマンドライン<!> quot;に沿って渡すことです。パラメータとして;安全ではありません。
しかし、必要なものにうまく対応し、スクリプトが常に開始され、中断することなく実行できるようにします。
これも参考になります: PHPの非同期シェルexec
shell_execコマンドはあなたが探しているものだと思います。
ただし、セーフモードでは無効になります。
これに関するPHPのマニュアル記事は次のとおりです。 http://php.net/shell_exec
これに関する記事があります: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
使用できる別のオプションがあります。スクリプトCLIを実行します...バックグラウンドで実行され、必要に応じてcronjobとして実行することもできます。
e.g
> #!/usr/bin/php -q
<?php
//process logs
?>
これはcronジョブとして設定でき、時間制限なしで実行されます。...この例は、Unixベースのオペレーティングシステム用です。
FYI 私はPHPスクリプトを無限ループで実行していますが、これは処理を行い、過去3か月間ノンストップで実行されています。
ignore_user_abort()
を使用できます-このようにすると、閉じてもスクリプトが実行され続けますブラウザを使用するか、別のページに移動します。
bastiandoeenの回答に加えて、ignore_user_abort(true);
を cUrlリクエストと組み合わせることができます。
低い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');
NB
cURLを1秒未満でタイムアウトさせる場合は、次を使用できます。 CURLOPT_TIMEOUT_MS、ただしバグ/ <!> quot; feature <!> quot; <!> quot; Unixライク システム<!> quot;値が<!> ltの場合、libcurlはすぐにタイムアウトします。 エラー<!> quot; cURLエラー(28)で1000ミリ秒:タイムアウトになりました<!> quot;。の この動作の説明は次のとおりです。
[...]
解決策は、CURLOPT_NOSIGNALを使用してシグナルを無効にすることです
長所
- メソッドを切り替える必要はありません(互換ウィンドウ<!> amp; linux)
- ヘッダーとバッファを介して接続処理を実装する必要はありません(ブラウザおよびPHPバージョンから独立)
短所
- カール拡張機能が必要
リソース
ズック。
これはうまくいくと確信しています:
<?php
pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]";
?>
「<!> amp;」は重要。プロセスが終了するのを待たないようシェルに指示します。
また、PHPでこのコードを使用できます(<!> quot; bastiandoeen <!> quot;のように)
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]";
?>
出力の前にStartBuffer()を呼び出し、クライアントに接続を閉じたい場合はEndBuffer()を呼び出すだけです。 EndBuffer()を呼び出した後のコードは、クライアント接続なしでサーバーで実行されます。
private function StartBuffer(){ @ini_set('zlib.output_compression',0); @ini_set('implicit_flush',1); @ob_end_clean(); @set_time_limit(0); @ob_implicit_flush(1); @ob_start(); } private function EndBuffer(){ $size = ob_get_length(); header("Content-Length: $size"); header('Connection: close'); ob_flush();ob_implicit_flush(1); }