web-dev-qa-db-ja.com

PHPバックグラウンドプロセス

PHPスクリプトを作成しようとしています。スクリプトは終了していますが、設計されたプロセスを完了するのに10分ほどかかります。これは問題ではありませんが、プロセスを開始してから10分後に戻って、生成されたログファイルを表示するようにページを保持することはできますか?

41
zuk1

さて、「 ignore_user_abort (true)」を使用できます

そのため、スクリプトは引き続き機能します(スクリプトの継続時間に注意してください。おそらく「 set_time_limit (0)」を追加してください)

ただし、ここでの警告:次の2行でスクリプトを停止することはできません。

ignore_user_abort(true); 
set_time_limit(0);

サーバーに直接アクセスし、そこでプロセスを強制終了できる場合を除きます! (そこに来て、無限ループを繰り返し、何度も自分自身を呼び出して、サーバーを金切り声で止め、叫びました...)

50
bastiandoeen

キューとキューを処理するための外部スクリプトが必要なようです。

たとえば、PHPスクリプトはデータベーステーブルにエントリを入れてすぐに戻る必要があります。その後、毎分実行されるcronはキューをチェックし、各ジョブのプロセスをフォークします。

ここでの利点は、Apacheスレッドを10分間ロックしないことです。

26
Gary Richardson

この種のプロセスをWindowsで実行すると、多くの問題が発生しました。私の状況は、「スクリプト」の応答を気にしなかったという点で少し異なっていました。スクリプトを開始し、仕事で忙しいときに他のページリクエストが通過できるようにしたかったのです。

何らかの理由で;他のリクエストがハングするか、約60秒後にタイムアウトする問題がありました(Apacheとphpの両方が約20分後にタイムアウトするように設定されていました)。また、Firefoxは5分後に(デフォルトで)タイムアウトするため、Firefoxの設定を変更しないと、ブラウザーを介して何が起こっているのかわかりません。

私は、プロセスを開くプロセスとプロセスを閉じるメソッドを使用して、次のようにCLIモードでPHPを開きました:

pclose(popen("start php myscript.php", "r"));

これは、(startを使用して)phpプロセスを開き、開始プロセスを強制終了しますが、phpを必要な期間実行します-再びプロセスを強制終了して手動でシャットダウンする必要があります。タイムアウトを設定する必要はなく、それを呼び出した現在のページを継続させて、詳細を出力することができます。

これに関する唯一の問題は、スクリプトにデータを送信する必要がある場合、別のソース経由で送信するか、「コマンドライン」に沿ってパラメーターとして渡すことです。これはそれほど安全ではありません。

しかし、必要なものにうまく対応し、スクリプトが常に開始され、中断することなく実行できるようにしました。

これはまた助けになるかもしれません: PHPの非同期シェルexec

6
warren

Shell_execコマンドはあなたが探しているものだと思います。

ただし、セーフモードでは無効になります。

PHPそれに関するマニュアル記事はこちらです: http://php.net/Shell_exec

それに関する記事がここにあります: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/

5
Jon

使用できる別のオプションがあります。スクリプトCLIを実行します...バックグラウンドで実行され、必要に応じてcronjobとして実行することもできます。

例えば

> #!/usr/bin/php -q

<?php

//process logs

?>

これはcronjobとして設定でき、時間制限なしで実行されます。..この例はUNIXベースのオペレーティングシステム用です。

参考までに、私はPHPスクリプトを無限ループで実行しています。このループは処理を行い、過去3か月間ノンストップで実行されています。

4
Ronald Conco

ignore_user_abort() を使用できます。ブラウザを閉じたり、別のページに移動しても、スクリプトは引き続き実行されます。

3
Greg

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を使用できますが、「Unixのようなシステム」にバグ/「機能」があります。 cURLエラー(28):タイムアウトに達しました。」この動作の説明は次のとおりです。

[...]

解決策は、CURLOPT_NOSIGNALを使用して信号を無効にすることです

長所

  • メソッドを切り替える必要はありません(互換性のあるWindowsとLinux)
  • ヘッダーとバッファを介して接続処理を実装する必要はありません(ブラウザおよびPHPバージョン)から独立しています)

cons

  • カール延長が必要

リソース

2
RafaSashi

Gearman について考えてください

Gearmanは、複数のマシンまたはプロセスに作業を委託するための汎用アプリケーションフレームワークです。これにより、アプリケーションはタスクを並行して完了し、処理の負荷を分散し、言語間で関数を呼び出すことができます。このフレームワークは、高可用性Webサイトからデータベース複製イベントのトランスポートまで、さまざまなアプリケーションで使用できます。

この拡張機能は、Gearmanクライアントおよびワーカーを作成するためのクラスを提供します。 -ソースPHPマニュアル

ギアマン の公式ウェブサイト

2
Gowri

ズク。

私はこれがうまくいくと確信しています:

<?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]";

?>
1
Nader