私の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)
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]
を追加して、システムの起動時にコマンドを開始することもできます。
よりシェル指向のアプローチを取ることもできます。 cron
でスクリプトを探し、スクリプトが停止した場合は再起動します。
crontab -e
を実行して、新しいcrontabを作成します。これにより、お気に入りのテキストエディタのウィンドウが表示されます。
開いたばかりのファイルにこの行を追加します
*/5 * * * * pgrep -f testing.py || Nohup python /home/you/scripts/testing.py > test.out
ファイルを保存してエディターを終了します。
新しいcrontab
を作成しました。これは5分ごとに実行され、スクリプトがまだ実行されていない限り、スクリプトを起動します。 cron
の素敵な小さなチュートリアルについては here を参照してください。 cron
の公式Ubuntuドキュメントは here です。
実行される実際のコマンドはpgrep
で、実行中のプロセスでコマンドラインに指定された文字列を検索します。 pgrep foo
は、foo
という名前のプログラムを検索し、その プロセス識別子 を返します。 pgrep -f
は、プログラム名だけでなく、プログラムの起動に使用されるコマンドライン全体を検索します(これはpythonスクリプトであるため便利です)。
||
記号は、「前のコマンドが失敗した場合にこれを行う」ことを意味します。そのため、スクリプトが実行されていない場合、pgrep
は何も見つからないため失敗し、スクリプトが起動されます。
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で強制終了されると、すぐに解放されますか?).
コマンドラインオプションを使用してテストプログラムに出力をリダイレクトさせ、単純なpythonスクリプトを使用してプログラムを無期限に再起動します。
import subprocess
while True:
try:
print subprocess.check_output(['python', 'testing.py'])
except KeyboardInterrupt:
break
このプログラムをバックグラウンドに置くことができ、停止したい場合は、単にそれをフォアグラウンドにプルして終了します。
これを本番環境で実際に使用するべきではありませんが、次のことができます。
#!/bin/sh
while true; do
Nohup python testing.py >> test.out
done &
何らかの理由でpythonプロセスが終了した場合、シェルループは続行して再起動し、必要に応じて.out
ファイルに追加します。オーバーヘッドはほとんどなく、設定にほとんど時間がかかりませんアップ。
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"
スーパーバイザーが必要です supervisor を使用できます。 pythonベースのスーパーバイザであるため、必要に応じて簡単に変更できます。
制御は、.iniファイル構文のファイルで行われます。
私の場合、迅速な解決策として、プログラムがエラーで終了したとき、または強制終了されたときにプログラムを実行し続けたいと考えました。一方、プログラムが正しく終了したときに実行を停止したかった(戻りコード= 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)
Terdonの答えについては、pgrep -f testing.py
here のコメントに従って、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
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