4

2つのPHPファイルがあります。1つのファイルはcaller.phpで、もう1つはworker.phpです。

caller.phpは(Linux)システムでworker.phpを開始し、caller.phpはすぐに終了する必要があります(worker.phpがサーバー上で動作している間)

worker.phpは時間がかかり、データベースまたはファイルにステータスを書き込みます。

'php worker.php'を起動するブラウザーでcaller.phpを開き、ブラウザーを閉じ、5分後に戻ってステータスを確認できるようにしたいです。(または、スクリプトは完了後にメールを送信します)-任意これを行う方法のアイデア?

4

3 に答える 3

2

クライアント接続を終了しても、処理を続行できます。すべて完了です。php / httpdグローバル設定で処理に時間がかかる場合は、phpタイムアウトを増やすこともできます。を参照してくださいset_time_limit();

これはあなたが尋ねたものとは正確には異なりますが、X / Y問題である可能性があると思うので、ここでは次の目的で使用できる手法を使用します。

  • 処理開始ページをユーザーに表示します。
  • ユーザー接続を閉じます。
  • より長い処理を開始します。

つまり、基本的に、これは「Xの実行方法」ではなく、説明されているニーズに答えます。

発信者

// Ignore user abort and set Connection close header
ignore_user_abort(true);
header("Connection: close");

// Start controlled buffering
ob_start();
echo "<h1>Processing started, come back tomorrow to see results</h1>";

// Get buffer length and manually add it to headers.
$size = ob_get_length();
header("Content-Length: $size");

// Flush buffers, user sees "Processing started" message.
ob_end_flush();
flush();

// At this point connection to client should be closed already.
// Here we start our worker, there is no need to do fork() or 
// anything like that. Client browser is not listening anymore.
// All we need to do is simply start working and start writing
// status logs to somewhere so that client can retrieve status
// with another request, let's say from checkworkerstatus.php
include "worker.php";
$worker = new worker();
$worker->start_long_processing();

一人で走り続けるcallerためにフォークしたり殺したりしませんか?worker

そうです、それは必要がないからです。

はい、「caller.phpは(Linux)システムでworker.phpを開始し、caller.phpはすぐに終了する必要があります(worker.phpがサーバー上で動作している間)」という動作を要求しました。ただし、マルチスレッドを実行したくない場合は、そのようにする必要はありません-phpを使用したシングルユーザーアプリ。ユーザーに1.何かを開始させ、2。実行したままにし、3。ユーザーを切断し、4。ユーザーがさらに何かを開始したり、すでに十分に退屈している場合は終了したりできる場所に戻ります。

もちろん、後ですべてflush();を何かに置き換えることができます。違いは、クライアントがリッスンしないため、すべての出力が/ dev/nullという名前のブラックホールに送られることです。たとえば、次のようなものでテストします。

...end_flush();
flush();

// At this point connection to client should be closed already.
echo "Nobody sees this message";
while(rand(0,10) != 1) {
    echo "Nobody sees this message";
    error_log(date("mdyHis")." Still running...");
    sleep(10);
}
...

詳細については、 http://php.net/features.connection-handlingを参照してください。バッファのフラッシュとユーザー接続の終了に問題があると思われる場合は、http://php.net/function.flush
もお読みください。PHPがマルチスレッドをサポートしない理由 についての別の質問(回答付き)もあります。

于 2012-07-02T21:08:15.747 に答える
1
  1. 発信者はワーカーを実行します
  2. ワーカーは/tmp/にFIFOファイルを作成し、進行状況について書き込みます(ソケットも使用できます)
  3. 発信者はこのファイルを読み取り、ユーザーに実際の進行状況を表示します

Apache / nginxを適切に構成すると、(私のように)同時に2つのPHPファイルを実行できるようになります。

posix_mkfifoについて読む必要があります:http://php.net/manual/en/function.posix-mkfifo.php 使用例もあります)。

于 2012-07-02T18:47:18.690 に答える
1

これは少し強力かもしれませんが、最も迅速で直接的な方法です。

  • 呼び出し元は<IFRAME>を使用してHTMLを作成します
  • IFRAMEのSRCはワーカーです(ここでは、呼び出し元はパラメーターをGET-paramsとしてワーカーに渡します)
  • ワーカーの最初の行は以下のコードにあります

コード:

ignore_user_abort(true);
set_time_limit(0);

ブラウザワーカーを閉じると(すべきです)、動作するようになります!

http://www.php.net/manual/en/function.ignore-user-abort.phpを参照してください

于 2012-07-02T19:01:39.360 に答える