2012-05-14 23 views
17

関数をタイムアウトする方法はありますか?私は仕事をするために10分持っています。ジョブは、ここでは、forループ含ま例ですPHPの関数のタイムアウト

<?php 
foreach($arr as $key => $value){ 
    some_function($key, $value); //This function does SSH and SFTP stuff 
} 
?> 

$のARRは、時にはより1分かかる場合があります)15個の要素とsome_functionを(有しています。実際には一度それは5分間ぶら下げられました。

関数呼び出しをタイムアウトして、$ arrの次の要素に移動する方法はありますか?

ありがとうございました!

+0

いくつかの質問:それは何で、10分にあなたを制限しますか? ssh/sftpジョブが実行されるかどうかは関係ありませんか?何らかのキューを使用してこの制限を回避できますか? – aurora

+0

10分ごとに実行されるcrontabスクリプトです。サーバーの状態を確認し、データベースを更新しています。私は1分後に応答が返ってこない場合、私はそのサーバーを遅いサーバーに設定しています... – Mo3z

答えて

13

これは実装によって異なります。 PHPの99%の機能がブロックされています。意味処理は、現在の機能が完了するまで続行されません。ただし、関数にループが含まれている場合は、特定の条件が満たされた後にループを中断する独自のコードを追加できます。

このような何か:

foreach ($array as $value) { 
    perform_task($value); 
} 

function perform_task($value) { 
    $start_time = time(); 

    while(true) { 
    if ((time() - $start_time) > 300) { 
     return false; // timeout, function took longer than 300 seconds 
    } 
    // Other processing 
    } 
} 

処理を中断することは可能ではない別の例:

foreach ($array as $value) { 
    perform_task($value); 
} 

function perform_task($value) { 
    // preg_replace is a blocking function 
    // There's no way to break out of it after a certain amount of time. 
    return preg_replace('/pattern/', 'replace', $value); 
} 
+0

ありがとうマイクが、私はsome_functionまたはperform_taskはコア機能であり、コアメソッドを変更しないようにしようとしています。 – Mo3z

+1

ルートに行く:新しいスクリプトexample.phpを作成し、some_functionでそのスクリプトを呼び出し、some_functionのset_time_limit ...ロジックを定義するとexample.phpで実行されます。 – Mo3z

+0

同じ問題、同じテクニック。 –

8

PHPはシングルスレッドです...あなたは別のプロセスをforkするためにあなたのOSの機能を使用する必要があります。

これを行う方法を知っている唯一の方法は、別の完全なプロセスをフォークするexecコマンドです。必要なものを別のスクリプトに入れ、スクリプトのexecを呼び出して、すぐに10分間スリープします。プロセスがまだ実行中である場合、10分でそれを殺す。 (コマンドラインで新しいPHPコードをバックグラウンドで実行し、コマンドラインから取得してexecコマンドから返すことで、PIDを取得する必要があります)。

+0

すべてのPHPがスレッド化されているわけではありません –

4

ループを開始する前に、time()を覚えている変数を設定してください。各繰り返しの最後に、現在のtime()が60秒を超えているかどうかを確認します。その場合、break。たとえば:

<?php 
$startTime=time(); 
foreach($arr as $key => $value){ 
    some_function($key, $value); //This function does SSH and SFTP stuff 
    if (time()-$startTime>60) break; //change 60 to the max time, in seconds. 
} 
?> 
+0

あなたの答えはDavidにありがとうございます。私はforループを壊す必要はありません、それは分以上かかる場合some_functionを壊す必要があります。 – Mo3z

1

set_time_limitをご覧ください。現在、関数自体は実行時間を考慮に入れているだけで、実際の5秒はわずか0.2秒の実行である可能性があるので、実際には必要ありません。しかし、リンクを見る理由はコメントのためです。ユーザーが投稿した解決策がいくつかあります。

5

「curl」を使用してこれを実装できます。 curlは - PHPから - HTTP/FTPの処理によく使われますが、ssh/sftpを含むもっと多くのプロトコルをサポートしています。私はcurlを使ってssh/sftp関連のことをしたことは一度もなかったので、私は追加の助言を与えることはできませんが、stackoverflowや他の場所で追加情報を見つけることができます。

リクエストのタイムアウトを設定するためのオプション "CURLOPT_TIMEOUT"があります(オプション "CURLOPT_CONNECTTIMEOUT"もあります)。ミリ秒の分解能でタイムアウトを指定することもできます(CURLOPT_TIMEOUT_MS/CURLOPT_CONNECTTIMEOUT_MS)。

とにかく:cronjobの場合、スクリプトは起動時に書き込みを行い、実行が終了すると削除します。あなたのスクリプト内でこのロックファイルをチェックすることができます。もしcronがあなたのスクリプトの前に最後の実行が終了したの前にトリガーしたら、それ以上何もせずにスクリプトを終了することができます。これにより、スクリプトが複数回並列に実行されることはありません。

あなたはCURLオプションの詳細を見つけても、PHPのドキュメント自体にカールすることができます

あなたが確認する必要があり、あなたのインストールlibcurlのことと/またはcurl for PHPはSSH/SFTPをサポートしていますが、

助けなど

希望

  • SFTP from within PHP
  • SFTP from PHP - undefined constant CURLOPT_PROTOCOLS and CURLPROTO_SFTP? ...

    7

    は何が欲しいのは、タイムアウトにSIGALRM信号をトリガするpcntl_alarm機能を使用することです。たとえば :

    // 10 minutes 
    pcntl_alarm(600); 
    pcntl_signal('SIGALRM', function() { print("I am done!\n"); exit(0); }); 
    

    これについての詳細はこちらPHPマニュアルを参照してください。http://php.net/manual/en/function.pcntl-alarm.php

    +2

    完全な実装は次のとおりです:https://gist.github.com/avalanche123/3085581 –