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


31

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

nohup python testing.py > test.out &

さて、Python script何らかの理由で上記のいずれかの段階で死ぬ可能性があります。

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

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

更新:

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)

回答:


24

Ubuntu(14.04、16.04以降でsystemdを使用するまで)では、cronジョブよりもupstartを使用できます。構成設定を/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]システムの起動時にコマンドを開始するように追加することもできます。


cronジョブを使用する場合、堅牢なPIDファイル処理のためのコードを実装するか、見つける必要があります。service / script / daemonにPIDファイル(通常は/ var / runの下にあります)を作成させ、ファイルの内容が古い(強制終了されたプロセスによって残されている)かどうかを起動コードでチェックする必要があります。この種のコードは、人種や角のないケースを書くのが驚くほど困難です。stackoverflow.com/questions/788411/...
ジム・デニス

@Zelda:ご提案ありがとうございます。Linux/ Unixの世界は初めてです。/etc/initファイルにどのような変更を加える必要がありますか?あなたは私のためのステップバイステップガイドを提供することができた場合は、その後、私は..何かを学び、正しいことを行うことができるようになります
アーセナル

@Webby私は答えをより完全にしました。出力用にファイルを開き、印刷ステートメントを書き直したくない場合sys.stdout = open(file_name, 'w')は、最初のようにできます。
ゼルダ14年

ゼルダありがとうございます。あなたの助けに感謝します。.私はいくつかの詳細で質問を更新しましたpx ax | grep testing.py。何も返さないの?理由は何ですか?
アーセナル14年

すべてをtry / except句に入れ、生成された例外とプログラムが終了したことをログファイルに書き込む必要があります。たぶん、printステートメントはstdoutに書き込めないため機能しません。
ゼルダ14年

20

よりシェル指向のアプローチを取ることもできます。あなたの持っているcronあなたのためのスクリプトを見て、それが死んだ場合、それを再起動します。

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

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

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

crontab5分ごとに実行される新しいスクリプトを作成し、既に実行されていない限りスクリプトを起動します。こちらの素敵な小さなチュートリアルをご覧くださいcron。Ubuntuの公式ドキュメントcronこちらです。

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

||シンボルの手段は、「前のコマンドが失敗した場合は、これを行います」。そのため、スクリプトが実行されていない場合、pgrep何も見つからずスクリプトが起動されるため失敗します。


ありがとうございます。しかし、私はLinuxとUNIXが初めてなので、crontabがどこにあるかわかりませんか?これは私のubuntuマシンのどこかのファイルですか?
アーセナル14年

@Webbyは更新された回答を参照してください。
テルドン

ありがとう、terdon .. crontab -epythonスクリプトがあるディレクトリからこのコマンドを実行できます。
アーセナル14年

1
@Webbyは、どこからでも実行できます。cronはスケジューリングデーモンであり、バックグラウンドで実行されるサービスです。pythonスクリプトが自分のディレクトリにない$PATH場合(どこからでも起動できないが、そのディレクトリにある必要がある場合)、更新された回答のようにスクリプトへのフルパスを使用します。
テルドン

ありがとう。今では理にかなっています。新しいcrontabを作成し、同じ単一行を1分間追加することでファイルを編集しました。 crontabファイル、それは1分後にtesting.pyを自動的に開始する必要がありますか?そして、Pythonスクリプトが実行されているかどうかを1分ごとにチェックし続けますか?はいの場合、crontab -eファイルを保存した後、ps ax | grep testing.pyと私はそのためのプロセスを見ることができませんか?
アーセナル14年

6

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

import subprocess

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

このプログラムをバックグラウンドに配置できます。停止したい場合は、フォアグラウンドに引っ張って強制終了します。


6

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

#!/bin/sh

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

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


6

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

しかし、initおよびPardusのPythonコード(特にmudurデーモン)の代替を見ることができます。

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

私が他のコメントでほのめかしたように、堅牢なPIDファイルの処理には注意が必要です。レースやコーナーケースが発生しやすい。PIDファイルがNFSまたはその他のネットワークファイルシステムに配置される可能性がある場合は注意が必要です(一部のアトミック性は、適切なローカル UNIX / Linuxファイルシステムのファイル処理セマンティクスがNFSの一部のバージョンおよび実装でなくなることを保証しますが、例えば)。また、UNIXでのファイルロックに関するセマンティクスには注意が必要です。(DOES AN flockまたはfcntlそれを保持しているプロセスは、例えば、SIGKILLで殺されたときにロックは、あなたのターゲットのOSで、速やかにリリースされます?)。


3

また、ps-watcherでmonitまたはプロセス監視を使用できます。

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の例を見てください


1

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

制御は、.iniファイル構文のファイルを使用します。


0

テルドンの答えは、私にとってはうまくいきません pgrep -f testing.pyでした。cronジョブのpidを取得します(-fオプションのため)。ただし、-fオプションを指定しないと、pgrepはtesting.pyを見つけられません。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

私の場合、簡単な修正として、エラーで終了したり、強制終了したときにプログラムを実行し続けたいと思いました。一方、プログラムが正しく終了したときに実行を停止したかった(戻りコード= 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

terdonの答えについては、pgrep -f testing.py内のコメントによると、偽を返すことはありませんここに

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

Mattの答えは、実行中のPythonスクリプトと一致するpgrep -f testing.pyため、pgrep 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.