web-dev-qa-db-ja.com

大きなPHPスクリプトを実行する方法は?

基本的に、1時間もかかるスクリプトを実行したいと思うかもしれません。

私が本当にやりたいのは、サードパーティのAPIを使用してユーザーにSMSを送信することです。したがって、基本的には、スクリプトに電話番号の配列を提供し、SMSを送信するメソッドを起動するのと同じです。

ただし、1 SMSを送信するのに5秒かかり、1000 SMSを送信したい場合、約1〜2時間です。set_time_limit()私は共有ホストにいるので。

これを行う1つの方法は、セッションに番号を保存し、各SMSを実行し、javascriptを使用してそのページを最後まで更新することです。この方法では、ブラウザーを開いたままにしておく必要があります。インターネット接続が切断されています。

だから、これを行うためのより良い方法はありますか?

私が欲しいものを説明するのに十分明確であることを願っていますか?タイムアウトせずに実行するのに数時間かかる可能性のある大きなスクリプトを実行したい。

ホストが許可する場合は、cronジョブが最適なソリューションです。 cronジョブは基本的に、特定の時間間隔でWebサーバーによって自動的に実行される通常のphpスクリプトです。必要に応じて、5分ごとに実行し、100のバッチで数値を処理するスクリプトを作成します(明らかに、時間間隔とバッチサイズを適切に調整する必要があります)。これにより、サーバーの負荷が軽減され、リソースを占有するためにホスティングプロバイダーとトラブルが発生するのを防ぐことができます。

スクリプトが処理する必要があるバッチを追跡するために、track_batchテーブルを設定します。これらの列は、問題へのアプローチ方法を適切に示しているはずです。

id、date_run、start_record、end_record、final_run

基本的に:

  • 最後のバッチ実行の日付を確認してください。現在のバッチの現在の日付(または使用することを選択した他の識別子)でない場合は、次に進みます。
  • 現在の日付の最後のバッチ実行wasの場合は、final_run列をチェックして、すべての数値の処理がすでに完了しているかどうかを確認します。
  • 処理する数値がまだある場合は、開始レコードと終了レコードをMySQLのLIMITと組み合わせて使用​​して、スクリプトが次のバッチを取得するために使用するdbクエリを作成します。
  • 番号を処理します。
  • このバッチのすべての情報をtrack_batchテーブルに保存します。
  • クエリが返す数値の量が最大バッチサイズよりも少ない場合は、最後に到達しており、final_run列を1に設定できます。

スクリプトを入手したら、cronジョブ自体を設定する必要があります。共有ホストには、これを行うための独自のカスタムインターフェイスがある可能性が高いため、スクリプトが機能するようになったら、共有ホストに尋ねるのがおそらく最適です。

5
Mathew

PHPコマンドラインまたはシェルスクリプト、cronジョブなどから実行されたスクリプトにはタイムアウトがありません。

CLIで呼び出されるスクリプトの場合、PHPスクリプトのタイムアウトを set_time_limit() 関数で動的に設定しても、効果はありません。

21
Bill Karwin

コマンドラインから実行されるPHPスクリプトは、max_execution_timeオプションの影響を受けません。
だから、心配する必要はまったくありません。

5

set_time_limit(0)を使用するのは最善のオプションではありません。これは、バグがあり、スクリプトが無限ループに入った場合でも、無期限に実行されることを意味するためです。

代わりに、各SMSに5秒かかると見積もる場合は、次のアプローチを使用してください。

while( $there_are_more_sms_to_be_sent ){
  set_time_limit(30); // enough spare time, just in case.

  // Do your sending, blah blah
}

これにより、制限時間は30秒に順次更新されます。もちろん、その単一のwhileで無限ループの問題が発生する可能性がありますが、そのwhile内に他の呼び出しがある場合、その制限により、それらの呼び出しのせいになります。

3
Seb

JavaScriptを使用する代わりに、ページにRefreshメタタグを追加することもできます。

<meta http-equiv="Refresh" content="2; url=http://yoururl/script.php&step=x" ?>

content="2; url=..の2つは、ページがロードされてから2秒後にURLをロードするようにブラウザに指示します。

0
Matijs

Cronジョブを実行できる場合

私は通常、キュー、マネージャー、およびワーカーを持っています。一度に一度SMSAPIを呼び出すことができない限り、このモデルが役立ちます。また、各ワーカーが自分で管理するため、タイムアウトについて心配する必要はありません。

私は次のようなものを持っています:

<?php
// PSEUDO CODE
// grab pending from queue

// <for> {
// update to running
exec("/usr/bin/php /path/to/send.php {$id} > /dev/null &");
// }

そしてsend.phpは各SMSを送信します。 cronジョブで設定できる最大頻度であるため、現在、これを300 /分の速度で実行しています。

0
Gabriel Sosa

あなたできるまたはあなたできないset_time_limit()を使用しますか?

できれば..それを使用してください:

<?php
// Runs forever and ever...
set_time_limit(-1);
?>
0
Thiago Belem