7

私は大きなPHPスクリプトを実行しています. その仕事を終えるのに一日
かかるかもしれませ ん.必要な限りバックグラウンドで実行します。ターミナルを使用して実行しました.PHPスクリプト自体には、終了するまでできるだけ長く実行するための設定があります:

set_time_limit(0); // run without timeout limit

別の分離されたPHPスクリプトから実行するため、この関数を使用します

ignore_user_abort(1); // ignore my abort

コマンドラインから直接実行するため、2つの選択肢があります..
1)スクリプトが終了するまで待つ
2)プロセス全体をキャンセルする

そして検索した後、次の関数を使用してバックグラウンドでメインの BIG PHP スクリプトを実行する外部 PHP スクリプトを作成することにより、可能な限り長くバックグラウンドで実行するという 3 番目の選択肢を提供する記事がありました。

exec("php bigfile.php");

つまり、ブラウザから通常どおりこの外部ページを開きignore_user_abort、バックグラウンドで実行し続けるため、心配することなく終了できます..それはまだ問題ではありません

問題は..不明な期間の後、スクリプトはその仕事を停止します..どうすればわかりますか? 動作する各レコードの現在の日時を外部ファイルに書き込むように指示したので、その外部ページを毎回更新して、更新が停止したかどうかを確認します。

不明な期間の後、実際には理由もなく停止します。スクリプトには停止などのメッセージが何もありません..何か問題が発生した場合は、レコードをスキップするように指示しました(何も問題は発生しません。それらはすべて同じ行で機能します。 1つが機能し、すべてが機能するはずです)

しかし、私の主な疑問は次のとおりです。

  • Apacheにはそれを殺すタイムアウトがあります
  • これは、バックグラウンドで PHP スクリプトを実行する適切な方法ではありませんでした
  • PHP であれ、Apache であれ、( MySQL !?)であれ、どこかにタイムアウトがあります。それ
    が私の最大の疑問です。エラーが発生した場合、スクリプト全体がクラッシュしますか? スクリプト全体をクラッシュさせるタイムアウトはありますか?while

それらのどれにも当てはまらない場合、現在スクリプトで正確に何が起こっているかをログに記録する方法はありますか? または、なぜクラッシュするのでしょうか? すべてをログに記録する詳細な方法はありますか?


更新

messagesのファイルでこれを見つけました/var/log/:

Dec 29 16:29:56 i0sa shutdown[5609]: shutting down for system halt
Dec 29 16:30:14 i0sa exiting on signal 15
Dec 29 16:30:28 i0sa syslogd 1.5.0#6: restart.
Dec 29 16:50:28 i0sa -- MARK --
            .....
Dec 29 18:50:31 i0sa -- MARK --
Dec 29 19:02:36 i0sa shutdown[3641]: shutting down for system halt
Dec 29 19:03:11 i0sa exiting on signal 15
Dec 29 19:03:48 i0sa syslogd 1.5.0#6: restart.

それはシステムの停止を意味します..私はこれが将来のクラッシュと試合時間でそれである可能性があることを確認しようとします.これが原因である可能性はありますか? なぜ ?私はサーバーメモリRAMを持っていますが、これmemory_limitは128Mですか?2GB

PS: サーバーを手動で数回再起動しました..しかし、これはシャットダウンと停止を示していますか?

4

9 に答える 9

6

そのような場合、私は次のような nohup コマンドを成功させて使用します。

nohup php  /home/cron.php >/dev/null  2>&1 &

その後、スクリプトが実行されているかどうかを次のように確認できます。

jobs -l

注:phpファイルのnohupコマンドパスを使用する場合、相対パスではなく絶対パスにする必要があります。作業が完了する前にその実行が停止するのを防ぐためだけに、あるphpファイルから別のphpファイルを呼び出すのはあまり優雅ではないと思います。

外部参照: http://en.wikipedia.org/wiki/Nohup

また、スクリプトにメモリリークがないことを確認してください。これは、「メモリ不足」のためにしばらくするとスクリプトがクラッシュします。

于 2012-12-30T11:40:41.337 に答える
2

nohupを使ってみましたか?

exec("nohup php bigfile.php &");

ホストが nohup コマンドを許可している場合、コマンドはバックグラウンドで実行され、exec を呼び出すスクリプトはすぐに続行されます。

于 2012-12-30T11:36:06.413 に答える
1

Osa、あなたの Apache はおそらくこれを殺したでしょう。他の人がきっとそうするように、考えられる原因について詳しく説明することができます。私はむしろあなたの質問の代わりにあなたの問題に答え、あなたtmuxが説明したタスクに使用することをお勧めします (または利用screenできtmuxない場合)。

したがって、あなたがすることはtmux、そこからスクリプトを開いて開始することです。で取り外し、ctrl-b d後で再度取り付けて、tmux attachどれくらい離れているかを確認します。切り離されている間は、停止せずにログアウトできます。

tmuxまだ必要ではありませんが、アプローチを理解するのに役立つかもしれない他のものの簡単な紹介http://victorquinn.com/blog/2011/06/20/tmux/ またはそれ以降 http://blog.hawkhost .com/2010/06/28/tmux-the-terminal-multiplexer/はまったく問題ありません

于 2012-12-30T11:33:49.133 に答える
0

1: popen()pclose()などを使用してPHPスクリプトを外部で実行することを検討してください。

2:マルチカールハンドラーを使用してcURLリクエストの長さを短縮できます

3:可能であれば、別の言語で試してみてください。PHPは、大規模なタスクではかなり遅いことが知られています。せいぜい数時間で完了できるのに、なぜ1日中かかるのでしょうか(40,000の異なるアドレスにネットワーク要求を行う必要があるため、数時間と言います)

4:そして、他の多くの人が言っているように、可能であればnohupを使用してみてください。

于 2012-12-30T11:55:23.453 に答える
0

ignore_user_abort を使用して apache を介して実行時間の長いスクリプトを実行するのは、汚い方法です。

最も簡単な方法は、GNU screenを使用することです。 screen と入力するだけで、現在のコンソール内の新しいコンソールにアタッチされ、スクリプトを起動し、ctrl-a dで画面から切り離すことができます(完全なマニュアルはこちら)。画面は続行します。サーバーから切断されても機能します。

画面に再接続するには、screen -rを使用します。実行中のスクリプトに戻ります。

最も難しい方法 (そして最もクリーンな方法) は、システム デーモンとして機能するようにスクリプトを書き直すことです。これを行うのに役立つライブラリがたくさんあります。pear のデーモン ライブラリを掘り下げることをお勧めします (例はこちら)。

メモリ制限の問題 (?) については、memory_limit 構成を更新する前に、スクリプトが現在の構成に書かれているよりも多くの RAM を消費しているかどうかを確認し、単純なps aux|grep phpを作成してRSSを探す必要があります。コラム、それはあなたのスクリプトが食べているすべてのメモリです.

于 2012-12-31T08:05:03.373 に答える
0

Apache を使用する場合、約 300 秒のタイムアウトがあります。定期的に呼び出すapache_reset_timeout();と、スクリプトを停止しない限り、スクリプトが永久に実行される可能性があります。

于 2012-12-30T11:38:16.583 に答える
0

まず第一に、私はこの問題に直面して解決しましたが、あなたの MySQL サーバーはこのハングについて責任を負わないことを強調したいと思います。

ini_set('max_execution_time', 1000);
ini_set('memory_limit', '50M');
set_time_limit(0); 

データをフェッチするたびに次を使用する必要があります。

$url_class = $URL_path;
//open connection
$ch_school_class = curl_init();
curl_setopt($ch_school_class, CURLOPT_URL, $url_class);
$result_school_class = curl_exec($ch_school_class);
//clean up
curl_close($ch_school_class);

//Each fetch like this 
$url_class = $URL_path;
//open connection
$ch_school_class = curl_init();
curl_setopt($ch_school_class, CURLOPT_URL, $url_class);
$result_school_class = curl_exec($ch_school_class);
//clean up
curl_close($ch_school_class);
于 2012-12-30T11:43:09.143 に答える
0

考慮すべきは実行時間だけではありません。次に考えられる原因は、スクリプトが max_memory_limit を超えていることです。

エラーログを確認/有効にしましたか? 静かに失敗している可能性があります。

于 2012-12-30T11:32:20.770 に答える