web-dev-qa-db-ja.com

Pythonスクリプトが強制終了または終了した場合に自動的に再起動する方法

私のPythonスクリプトは、Ubuntuマシン(12.04)のバックグラウンドで次のように実行しています-

Nohup python testing.py > test.out &

さて、ある段階で、私のPython scriptが何らかの理由で死ぬ可能性があります。

したがって、何らかの理由で強制終了された場合、上記のPythonスクリプトを自動的に再起動できるbashシェルスクリプトにある種のcron agentを含めることを考えています。

これは可能ですか?はいの場合、この種の問題を解決する最良の方法は何ですか?

更新:

このようなtesting.confファイルを作成した後-

chdir /tekooz
exec python testing.py
respawn

Sudoコマンドの下で実行して起動しましたが、ps axを使用してそのプロセスが背後で実行されているのが見えませんか?

root@bx13:/bezook# Sudo start testing
testing start/running, process 27794
root@bx13:/bezook# ps ax | grep testing.py
27806 pts/3    S+     0:00 grep --color=auto testing.py

Px axが何も表示しない理由は何ですか?プログラムが実行されているかどうかを確認するにはどうすればよいですか?

これは私のpythonスクリプトです-

#!/usr/bin/python
while True:
    print "Hello World"
    time.sleep(5)
34
arsenal

Ubuntuでは(14.04、16.04以降、systemdを使用するまで)、upstartを使用して実行できます。cronジョブよりも優れています。構成設定を/etc/initに入れ、必ず respawn を指定します

最小限のファイル/etc/init/testing.confにすることができます(rootとして編集):

chdir /your/base/directory
exec python testing.py
respawn

そして/your/base/directory/testing.pyでテストできます:

from __future__ import print_function

import time

with open('/var/tmp/testing.log', 'a') as fp:
    print(time.time(), 'done', file=fp)
    time.sleep(3)

で始まる:

Sudo start testing

(別のウィンドウで)何が起こるかを追跡するには:

tail -f /var/tmp/testing.log

そして停止:

Sudo stop testing

[start on][2]を追加して、システムの起動時にコマンドを開始することもできます。

24
Zelda

よりシェル指向のアプローチを取ることもできます。 cronでスクリプトを探し、スクリプトが停止した場合は再起動します。

  1. crontab -eを実行して、新しいcrontabを作成します。これにより、お気に入りのテキストエディタのウィンドウが表示されます。

  2. 開いたばかりのファイルにこの行を追加します

    */5 * * * * pgrep -f testing.py || Nohup python /home/you/scripts/testing.py > test.out
    
  3. ファイルを保存してエディターを終了します。

新しいcrontabを作成しました。これは5分ごとに実行され、スクリプトがまだ実行されていない限り、スクリプトを起動します。 cronの素敵な小さなチュートリアルについては here を参照してください。 cronの公式Ubuntuドキュメントは here です。

実行される実際のコマンドはpgrepで、実行中のプロセスでコマンドラインに指定された文字列を検索します。 pgrep fooは、fooという名前のプログラムを検索し、その プロセス識別子 を返します。 pgrep -fは、プログラム名だけでなく、プログラムの起動に使用されるコマンドライン全体を検索します(これはpythonスクリプトであるため便利です)。

||記号は、「前のコマンドが失敗した場合にこれを行う」ことを意味します。そのため、スクリプトが実行されていない場合、pgrepは何も見つからないため失敗し、スクリプトが起動されます。

21
terdon

UNIX/Linuxでプロセスを監視および再起動するには、いくつかの方法があります。最も古いものの1つは、古いSysV initシステムを使用している場合の/ etc/inittab ...の "respawn"エントリです。別の方法は、DJ Bernsteinのdaemontoolsパッケージのスーパーバイザデーモンを使用することです。その他のオプションは、Ubuntuの機能を使用することですupstart...またはsystemdまたはその他。

しかし、特に alternatives init とPython Pardus:mudur デーモンのコード)を見ることができます。

Cronジョブ(およびPIDファイル処理)を使用する場合は、これを読んで PEP 314 を検討し、おそらくそのリファレンス実装を使用することを検討してください。

他のコメントで触れたように、堅牢なPIDファイルの処理は注意が必要です。レースやコーナーケースになりやすいです。 PIDファイルがNFSまたはその他のネットワーク化されたファイルシステムに到達する可能性がある場合、トリッキーになります(一部のアトミック性は、適切なlocalUNIX/Linuxファイルシステムは、NFSの一部のバージョンや実装ではなくなります(たとえば)。また、UNIXでのファイルロックに関するセマンティクスは注意が必要です。 (たとえば、ターゲットOSでflockまたはfcntlロックは、それを保持しているプロセスがSIGKILLで強制終了されると、すぐに解放されますか?).

6
Jim Dennis

コマンドラインオプションを使用してテストプログラムに出力をリダイレクトさせ、単純なpythonスクリプトを使用してプログラムを無期限に再起動します。

import subprocess

while True:
    try:
        print subprocess.check_output(['python', 'testing.py'])
    except KeyboardInterrupt:
        break

このプログラムをバックグラウンドに置くことができ、停止したい場合は、単にそれをフォアグラウンドにプルして終了します。

6
Anthon

これを本番環境で実際に使用するべきではありませんが、次のことができます。

#!/bin/sh

while true; do
  Nohup python testing.py >> test.out
done &

何らかの理由でpythonプロセスが終了した場合、シェルループは続行して再起動し、必要に応じて.outファイルに追加します。オーバーヘッドはほとんどなく、設定にほとんど時間がかかりませんアップ。

6
K3---rnc

monitまたは ps-watcherによるプロセス監視 も使用できます

Monitは、UNIXシステム上のプロセス、プログラム、ファイル、ディレクトリ、およびファイルシステムを管理および監視するためのオープンソースユーティリティです。 Monitは自動メンテナンスと修復を行い、エラー状況で意味のある因果的アクションを実行できます。

これがあなたのシナリオの例です:

check process myprocessname
        matching "myprocessname"
        start program = "Nohup /usr/bin/python /path/testing.py > /tmp/test.out &"
        stop program = "/usr/bin/killall myprocessname"

monitの例を見てください

3
Rahul Patil

スーパーバイザーが必要です supervisor を使用できます。 pythonベースのスーパーバイザであるため、必要に応じて簡単に変更できます。

制御は、.iniファイル構文のファイルで行われます。

1
user41123

私の場合、迅速な解決策として、プログラムがエラーで終了したとき、または強制終了されたときにプログラムを実行し続けたいと考えました。一方、プログラムが正しく終了したときに実行を停止したかった(戻りコード= 0)

私はBashでテストしました。他のシェルでも問題なく機能するはずです。

#!/bin/sh

echo ""
echo "Use: $0 ./instagram.py"
echo ""

echo "Executing $1 ..."

EXIT_CODE=1
(while [ $EXIT_CODE -gt 0 ]; do
    $1
    # loops on error code: greater-than 0
    EXIT_CODE=$?
done)
0
user9869932

Terdonの答えについては、pgrep -f testing.pyhere のコメントに従って、falseが返されることはありません:

問題は、cronがコマンドを実行するためにシェルを生成し、-fを使用しているため、そのシェルの引数がpgrepによって照合されることだと思います

マットの答えは、pgrep -f testing.pyは、pgrep pythonは、実行中のすべてのPythonスクリプトに一致します。したがって、2つのPythonスクリプトcronjobの場合、2番目のcronjobは実行されません。

そして、私は解決するための解決策を見つけましたpgrep -f testing.pyここのコメント: https://askubuntu.com/questions/1014559/running-pgrep-in-a-crontab?noredirect=1&lq=1

2つのPythonスクリプトを実行するための私のcron:

* * * * * pgrep -f '^/usr/bin/python36 /home/ec2-user/myscript1\.py' || Nohup /usr/bin/python36 /home/ec2-user/myscript1.py

0 * * * * pgrep -f '^/usr/bin/python36 /home/ec2-user/myscript2\.py' || Nohup /usr/bin/python36 /home/ec2-user/myscript2.py
0
Frank

pgrep -f testing.pyが「失敗」することはなかったので、Terdonの答えはうまくいきませんでした。 cronジョブのpidを取得します(-fオプションのため)。ただし、-fオプションを指定しないと、testing.pyというプロセスがないため、pgrepはtesting.pyを見つけることができません。

これに対する私の解決策は変更することでした

pgrep -f testing.py

pgrep -f testing.py | pgrep python

つまり、完全なcrontabジョブは次のようになります。

*/5 * * * * pgrep -f testing.py | pgrep python || Nohup python /home/you/scripts/testing.py > test.out
0
Matt