web-dev-qa-db-ja.com

長期(無限)Pythonプロセスを実行するにはどうすればよいですか?

私は最近、PythonをWeb開発に使用する実験を始めました。これまでのところ、Apacheとmod_wsgiおよびDjangoのWebフレームワーク= Python 2.7。ただし、プロセスを常に実行している、情報を更新しているなどの問題がありました。

「daemonManager.py」を呼び出すスクリプトを作成しました。これは、すべてまたは個々のpython更新ループ(それらをデーモンと呼ぶ必要がありますか?)実行し、無限ループを開始する特定の関数のモジュールです。PIDファイルを/var/runに保存してプロセスを追跡します。これまでのところ良好です。私が遭遇した問題は次のとおりです。

  • 時々、プロセスの1つが終了します。私は午前中にpsをチェックしましたが、プロセスは完了しました。エラーはログに記録されておらず(loggingモジュールを使用しています)、考えられるすべての例外をカバーしてログに記録しています。また、これらの終了プロセスは私のコードとは関係がないと思います。すべてのプロセスが完全に異なるコードを実行し、ほぼ同じ間隔で終了するためです。もちろん私は間違っている可能性があります。 Pythonプロセスが数日/数週間実行された直後に死ぬのは正常ですか?この問題への取り組み方は?他のデーモンがまだ実行されているかどうかを定期的にチェックする別のデーモンを書く必要があります?そのデーモンが停止した場合はどうなりますか?これをどう処理するか途方に暮れています。

  • プロセスがまだ実行中かどうかをプログラムで知るにはどうすればよいですか? PIDファイルを/var/runに保存し、プロセスが実行されているかどうかを判断するためにPIDファイルが存在するかどうかを確認しています。ただし、プロセスが予期しない原因で停止した場合、PIDファイルは残ります。したがって、プロセスがクラッシュするたびに(週に数回)これらのファイルを削除する必要がありますが、これは目的に反します。ファイル内のPIDでプロセスが実行されているかどうかを確認できたと思いますが、別のプロセスが開始され、デッドプロセスのPIDが割り当てられている場合はどうなりますか?私のデーモンは、長い間死んでいても、プロセスは正常に動作していると考えます。繰り返しますが、私はこれにどう対処するか途方に暮れています。

ベストを実行する方法についての有用な答えPythonプロセス、できれば上記の問題にいくつかの光を当てると、私は受け入れます


UbuntuマシンでApache 2.2.14を使用しています。
My Pythonバージョンは2.7.2です

31
Hubro

これは、長時間実行プロセス(LRP)を管理するためのone方法であり、事実上のストレッチではないことを明記して開きます。

私の経験では、可能な限り最高の製品は、サポートしている技術を他のライブラリに委任しながら、対処している特定の問題に集中することから来ています。この場合、私はバックグラウンドプロセス(ダブルフォークの技術)、監視、およびログリダイレクトの動作について言及しています。

私のお気に入りのソリューションは http://supervisord.org/ です

スーパーバイザのようなシステムを使用して、基本的に、「無限」ループに陥ったままタスクを実行する従来のpythonスクリプトを記述します。

#!/usr/bin/python

import sys
import time

def main_loop():
    while 1:
        # do your stuff...
        time.sleep(0.1)

if __name__ == '__main__':
    try:
        main_loop()
    except KeyboardInterrupt:
        print >> sys.stderr, '\nExiting by user request.\n'
        sys.exit(0)

この方法でスクリプトを作成すると、開発とデバッグが簡単で便利になります(ターミナルでスクリプトを簡単に開始/停止し、イベントが展開するにつれてログ出力を監視できます)。本番環境に投入するときは、スクリプトを呼び出すスーパーバイザー構成を定義するだけです(「プログラム」を定義するためのfullの例を示します)。オプションは次のとおりです: http://supervisord.org/configuration.html#program-x-section-example )。

スーパーバイザーにはたくさんの設定オプションがあるため、ここでは列挙しませんが、説明した問題を具体的に解決するとします。

  • 背景/デーモン化
  • PIDトラッキング(プロセスが予期せず終了した場合にプロセスを再起動するように構成できます)
  • 通常はスクリプトにログインし(印刷ではなくロギングモジュールを使用する場合はストリームハンドラー)、スーパーバイザーにファイルをリダイレクトさせます。
26
Owen Nelson

私はあなたがUnix/Linuxを実行していると思いますが、あなたは本当に言っていません。私はあなたの問題について直接アドバイスをしません。だから私はこの質問に対する「正しい」答えになるとは思っていません。しかし、ここで探求することがいくつかあります。

まず、デーモンがクラッシュした場合は、修正する必要があります。バグのあるプログラムのみがクラッシュします。おそらく、それらをデバッガーの下で起動し、それらがクラッシュしたときに何が起こるかを確認する必要があります(可能な場合)。これらのプロセスにトレースログがありますか?そうでない場合は、追加してください。クラッシュの診断に役立つ場合があります。

次に、デーモンはサービスを提供していますか(パイプを開いてリクエストを待機しています)、または定期的なクリーンアップを実行していますか?定期的なクリーンアッププロセスである場合は、無限ループで実行するのではなく、cronを使用して定期的に起動する必要があります。 cronプロセスは、デーモンプロセスよりも優先する必要があります。同様に、それらがポートとサービス要求を開くサービスである場合、それらをINETDで動作させることを検討しましたか?繰り返しになりますが、単一のデーモン(inetd)は、一連のデーモンプロセスよりも優先されます。

3番目に、PIDをファイルに保存することは、ご存じのようにあまり効果的ではありません。おそらく、セマフォのような共有IPCがより適切に機能します。ここには詳細はありません。

第4に、ウェブサイトのコンテキストで実行するためのものが必要になる場合があります。メンテナンスURLでwgetを呼び出すcronプロセスを使用しています。特別なcookieを設定し、wgetコマンドラインでcookie情報を含めます。特別なCookieが存在しない場合は、メンテナンスプロセスを実行するのではなく、403を返します。ここでのもう1つの利点は、通常のWebページを提供するコードがメンテナンスプロセスを提供するため、データベースへのログインおよびその他の環境問題の回避です。

それがあなたにアイデアを与えることを願っています。できるならデーモンを避けるのが一番のスタートだと思います。 mod_wsgi内でpythonを実行できる場合、複数の「環境」をサポートする必要がなくなります。一度に何日も実行した後に失敗したプロセスのデバッグは、残酷です。

2
jmucchiello

Pythonプロセスは、プログラムにメモリリークがない場合、Pythonインタプリタ、またはPythonライブラリ/モジュール。メモリリークが発生しても、64ビットマシンに十分なスワップスペースがある場合は、永久に実行できる可能性があります。10年、 Pythonプロセスは、限られたハードウェア上でほぼ2年間、問題なくハードウェアを移動する必要がある前に存続しました。)

Linuxディストリビューションを使用した場合、プログラムが終了したときにプログラムが再起動することを保証する SysVスタイルinit -_/etc/inittab_とinit(8)は、起動時にプログラムを生成し、プログラムが停止した場合は再生成します。 (多くのディストリビューションが最近使用している新しい upstartinit- replacementを使用してこの機能を複製するメカニズムを知りません。不可能ではありません。 、それを行う方法がわかりません。)

しかし、過去のinit(8)のメカニズムでさえ、一部の人が好むほど柔軟ではありませんでした。 DJBによる daemontools パッケージは、デーモンを永遠に存続させることを目的としたプロセス制御および監視ツールの一例です。 Linux-HA スイートは別の同様のツールを提供しますが、このタスクに正当化するには多すぎる「追加」機能を提供する可能性があります。 monit は別のオプションです。

2
sarnold