Cara memulai ulang skrip Python secara otomatis jika terbunuh atau mati

31

Saya menjalankan skrip Python saya di latar belakang di mesin Ubuntu saya (12,04) seperti ini -

nohup python testing.py > test.out &

Sekarang, mungkin saja pada tahap tertentu di atas saya Python scriptbisa mati untuk alasan apa pun.

Jadi saya berpikir untuk memiliki semacam cron agentskrip bash shell yang dapat memulai kembali skrip Python saya di atas secara otomatis jika terbunuh karena alasan apa pun.

Apakah ini mungkin dilakukan? Jika ya, lalu apa cara terbaik untuk memecahkan masalah seperti ini?

MEMPERBARUI:

Setelah membuat testing.conffile seperti ini -

chdir /tekooz
exec python testing.py
respawn

Saya berlari di bawah perintah sudo untuk memulainya tetapi saya tidak bisa melihat proses berjalan di belakang menggunakan ps kapak?

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

Tahu kenapa px ax tidak menunjukkan apa-apa padaku? Dan bagaimana saya memeriksa apakah program saya berjalan atau tidak?

Ini adalah skrip python saya -

#!/usr/bin/python
while True:
    print "Hello World"
    time.sleep(5)
gudang senjata
sumber

Jawaban:

24

Di Ubuntu (hingga 14,04, 16,04 dan yang lebih baru menggunakan systemd) dapat menggunakan pemula untuk melakukannya, lebih baik daripada pekerjaan cron. Anda memasukkan pengaturan konfigurasi /etc/initdan pastikan Anda menentukan respawn

Ini bisa berupa file minimal /etc/init/testing.conf(sunting sebagai root):

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

Dan Anda dapat menguji dengan /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)

dan mulai dengan:

sudo start testing

dan ikuti apa yang terjadi (di jendela lain) dengan:

tail -f /var/tmp/testing.log

dan berhenti dengan:

sudo stop testing

Anda juga dapat menambahkan [start on][2]agar perintah mulai saat boot sistem.

Zelda
sumber
Jika Anda menggunakan pekerjaan cron maka Anda ingin mengimplementasikan atau menemukan beberapa kode untuk penanganan file PID yang kuat. Anda ingin layanan / skrip / daemon Anda membuat file PID (terletak di bawah / var / run) secara konvensional dan memeriksa kode permulaannya apakah konten file sudah basi (ditinggalkan oleh proses yang terbunuh). Jenis kode ini sangat sulit untuk ditulis bebas dari kasus balapan dan sudut. stackoverflow.com/questions/788411/...
Jim Dennis
@Zelda: Terima kasih atas sarannya. Saya baru mengenal dunia Linux / Unix .. Jenis perubahan apa yang harus saya buat dalam /etc/initfile? Jika Anda dapat memberikan panduan langkah demi langkah untuk saya, maka saya akan dapat mempelajari sesuatu dan melakukan hal yang benar ..
arsenal
@Webby saya membuat jawabannya lebih lengkap. Jika Anda tidak ingin membuka file untuk output dan menulis ulang pernyataan cetak Anda, Anda dapat melakukan sesuatu seperti sys.stdout = open(file_name, 'w')di awal.
Zelda
Zelda terima kasih. Menghargai bantuan Anda .. Saya memperbarui pertanyaan dengan beberapa detail .. Saya mencoba melakukan seperti ini untuk melihat apakah testing.py saya berjalan atau tidak .. Tidak menunjukkan kepada saya apakah itu berjalan atau tidak .. px ax | grep testing.py.. Tidak mengembalikan apa-apa padaku? Ada yang tahu kenapa?
arsenal
Anda harus meletakkan semuanya dalam coba / kecuali klausa dan menulis ke file log pengecualian apa yang dihasilkan dan bahwa program keluar. Mungkin pernyataan cetak tidak berfungsi karena tidak bisa menulis ke stdout.
Zelda
20

Anda juga bisa mengambil pendekatan yang lebih berorientasi shell. Periksalah cronskrip Anda dan jalankan kembali jika mati.

  1. Buat crontab baru dengan menjalankan crontab -e. Ini akan memunculkan jendela editor teks favorit Anda.

  2. Tambahkan baris ini ke file yang baru saja dibuka

    */5 * * * * pgrep -f testing.py || nohup python /home/you/scripts/testing.py > test.out
  3. Simpan file dan keluar dari editor.

Anda baru saja membuat yang baru crontabyang akan berjalan setiap 5 menit dan meluncurkan skrip Anda kecuali sudah berjalan Lihat di sini untuk tutorial kecil yang menyenangkan cron. Dokumentasi Ubuntu resmi pada cronyang di sini .

Perintah aktual yang dijalankan adalah pgrepyang mencari proses yang berjalan untuk string yang diberikan pada baris perintah. pgrep fooakan mencari program yang bernama foodan mengembalikan pengenal prosesnya . pgrep -fmembuatnya mencari seluruh baris perintah yang digunakan untuk meluncurkan program dan tidak hanya nama program (berguna karena ini adalah skrip python).

The ||berarti simbol "melakukan hal ini jika perintah sebelumnya gagal". Jadi, jika skrip Anda tidak berjalan, pgrepkehendak gagal karena tidak akan menemukan apa pun dan skrip Anda akan diluncurkan.

terdon
sumber
Terima kasih .. Tapi saya baru mengenal linux dan unix jadi tidak tahu di mana crontab? Apakah ini file di mesin ubuntu saya di suatu tempat?
arsenal
@Webby lihat jawaban yang diperbarui.
terdon
Terima kasih terdon .. Saya dapat menjalankan perintah ini crontab -edari direktori di mana skrip python saya .. Benar?
arsenal
1
@Webby Anda dapat menjalankannya dari mana saja Anda inginkan. cronadalah daemon penjadwalan, ini adalah layanan yang berjalan di latar belakang. Jika skrip python Anda tidak ada di Anda $PATH(jika Anda tidak dapat meluncurkannya dari mana saja tetapi perlu berada di direktori-nya) gunakan path lengkap ke skrip seperti pada jawaban saya yang diperbarui.
terdon
Terima kasih. Sekarang masuk akal .. Saya baru saja membuat crontab baru dan mengedit file dengan menambahkan satu baris yang sama tetapi selama 1 menit .. Saya sudah membuat skrip Hello World Python berputar sementara True dinamai testing.py .. Setelah menyimpan file crontab, seharusnya secara otomatis memulai testing.py setelah 1 menit? Dan kemudian terus memeriksa setiap 1 menit apakah skrip python berjalan atau tidak? Jika ya, setelah menyimpan file crontab -e, saya melakukan ps ax | grep testing.py dan saya tidak dapat melihat proses apa pun untuk itu?
arsenal
6

Anda dapat meminta program pengujian mengarahkan ulang output menggunakan opsi commandline dan kemudian menggunakan skrip python sederhana untuk memulai kembali program tanpa batas:

import subprocess

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

Anda dapat meletakkan program ini di latar belakang, dan begitu Anda ingin berhenti, tarik saja ke latar depan dan bunuh.

Anthon
sumber
6

Anda seharusnya tidak menggunakan ini untuk produksi, tetapi Anda bisa:

#!/bin/sh

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

Jika, karena alasan apa pun, proses python keluar, loop shell akan melanjutkan dan me-restart, menambahkan .outfile yang diinginkan. Hampir tidak ada overhead dan membutuhkan sedikit waktu untuk menyiapkan.

K3 --- rnc
sumber
6

Ada beberapa cara untuk memantau dan memulai kembali proses di bawah UNIX / Linux. Salah satu yang tertua adalah entri "respawn" di / etc / inittab ... jika Anda menggunakan sistem init SysV lama. Metode lain adalah dengan menggunakan daemon pengawas dari paket daemontools DJ Bernstein . Opsi lainnya adalah menggunakan fitur di Ubuntu pemula ... atau systemd atau lainnya.

Tetapi Anda dapat melihat alternatif init dan kode Python untuk Pardus: daemon mudur pada khususnya.

Jika Anda memutuskan untuk menggunakan pekerjaan cron (dan penanganan file PID) maka pertimbangkan untuk membaca PEP 3143 ini dan mungkin menggunakan implementasi rujukannya.

Seperti yang saya singgung di komentar saya yang lain, penanganan file PID yang kuat itu rumit. Ini rentan terhadap kasus balapan dan sudut. Semakin rumit jika ada kemungkinan file PID Anda berakhir pada NFS atau sistem file jaringan lainnya (sebagian dari atomisitas menjamin Anda dapatkan dengan semantik penanganan file pada sistem file UNIX / Linux lokal yang sesuai hilang pada beberapa versi dan implementasi NFS, sebagai contoh). Juga semantik di sekitar penguncian file di bawah UNIX bisa rumit. (Apakah kunci flockatau fcntldilepaskan segera, di OS target Anda, ketika proses memegangnya dibunuh dengan SIGKILL, misalnya?).

Jim Dennis
sumber
3

Anda juga dapat menggunakan pemantauan monit Atau Proses dengan ps-watcher

Monit adalah utilitas sumber terbuka untuk mengelola dan memantau, proses, program, file, direktori dan sistem file pada sistem UNIX. Monit melakukan pemeliharaan dan perbaikan otomatis dan dapat melakukan tindakan kausal yang bermakna dalam situasi kesalahan.

Berikut ini contoh skenario Anda:

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

Lihatlah contoh monit

Rahul Patil
sumber
1

Anda membutuhkan penyelia, Anda bisa menggunakan penyelia . Ini adalah pengawas berbasis python, oleh karena itu mudah untuk memodifikasi jika perlu.

Kontrol dengan file dengan sintaks file .ini.

pengguna41123
sumber
0

Jawaban Terdon, tidak bekerja untuk saya, karena pgrep -f testing.pytidak pernah 'gagal'. Itu akan mengambil pid untuk pekerjaan cron (karena opsi -f). Namun, tanpa opsi -f pgrep tidak akan menemukan testing.py karena tidak ada proses yang disebut testing.py.

Solusi saya untuk ini adalah berubah

pgrep -f testing.py

untuk

pgrep -f testing.py | pgrep python

ini berarti pekerjaan penuh crontab adalah:

*/5 * * * * pgrep -f testing.py | pgrep python || nohup python /home/you/scripts/testing.py > test.out
Mat
sumber
0

Dalam kasus saya, sebagai perbaikan cepat, saya ingin menjaga program saya berjalan ketika keluar dengan kesalahan atau itu dibunuh. Di sisi lain, saya ingin menghentikan eksekusi ketika program diakhiri dengan benar (kode pengembalian = 0)

Saya sudah mengujinya di Bash. Ini seharusnya bekerja dengan baik di shell lain

#!/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)
pengguna9869932
sumber
0

Untuk jawaban terdon, pgrep -f testing.pytidak akan pernah kembali salah menurut komentar di sini :

Saya pikir masalahnya adalah bahwa cron menumbuhkan shell untuk menjalankan perintah Anda, dan argumen shell itu dicocokkan dengan pgrep karena Anda menggunakan -f

Untuk jawaban Matt, pgrep -f testing.pytidak berguna karena pgrep pythoncocok dengan skrip Python yang sedang berjalan. Jadi jika dua skrip Python cronjob, cronjob kedua tidak akan pernah berjalan.

Dan kemudian saya menemukan solusi untuk menyelesaikannya pgrep -f testing.pydi komentar di sini: https://askubuntu.com/questions/1014559/running-pgrep-in-a-crontab?noredirect=1&lq=1

Cron saya untuk menjalankan dua skrip Python:

* * * * * 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
jujur
sumber