Python betiği öldürülür veya ölürse otomatik olarak nasıl yeniden başlatılır


31

Python betiğimi Ubuntu makinemde (12.04) arka planda çalıştırıyorum böyle -

nohup python testing.py > test.out &

Şimdi, bir aşamada yukarıdakilerimin Python script, herhangi bir sebeple ölebileceği olabilir.

Bu yüzden cron agent, herhangi bir nedenden ötürü öldürülürse yukarıdaki Python betiğimi otomatik olarak yeniden başlatabilecek bir çeşit bash shell betiği kullanmayı düşünüyorum.

Bunu yapmak mümkün mü? Eğer evet ise, o zaman bu tür problemleri çözmenin en iyi yolu nedir?

GÜNCELLEŞTİRME:

testing.confBu gibi dosya oluşturduktan sonra -

chdir /tekooz
exec python testing.py
respawn

Başlatmak için sudo komutunun altında koştum ancak ps ax kullanarak bu işlemin arkasında çalıştığını göremiyorum.

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'in neden hiçbir şey göstermediği hakkında bir fikrin var mı? Programımın çalışıp çalışmadığını nasıl kontrol edebilirim?

Bu benim python betiğim -

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

Yanıtlar:


24

Ubuntu'da (14.04, 16.04'e ve daha sonra systemd kullanın) bunu başlatmak için bir cron işinden daha iyi bir başlangıç ​​yapabilir. Bir config kurulumu /etc/inityaptınız ve respawn belirttiğinizden emin olun.

Minimal bir dosya olabilir /etc/init/testing.conf(farklı düzenlenebilir root):

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

Ve şu şekilde test edebilirsiniz /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)

ve ile başlayın:

sudo start testing

ve olanları (başka bir pencerede) aşağıdakilerle izleyin:

tail -f /var/tmp/testing.log

ve ile durdurmak:

sudo stop testing

[start on][2]Komutu sistemin önyüklemesinde başlatmak için de ekleyebilirsiniz .


Bir cron işi kullanıyorsanız, sağlam PID dosyası işleme için bir kod uygulamak veya kod bulmak istersiniz. Hizmetinizin / script / daemon'un bir PID dosyası oluşturmasını (geleneksel / / var / run altında bulunur) ve başlangıç ​​içeriğinin dosya içeriğinin eskimiş olup olmadığını kontrol etmesini (öldürülmüş bir işlem tarafından bırakılmasını) istersiniz. Bu tür bir kod, yarışlardan ve köşe davalarından kurtulmak için şaşırtıcı bir şekilde zordur. stackoverflow.com/questions/788411/…
Jim Dennis

@Zelda: Öneriniz için teşekkürler .. Linux / Unix dünyasında yeniyim .. Dosyada ne tür değişiklikler yapmam gerekiyor /etc/init? Benim için adım adım rehberlik edersen, o zaman bir şeyler öğrenebilirim ve doğru şeyi yapabilirim ..
arsenal

@Webby Cevabı daha eksiksiz yaptım. Çıktı için bir dosya açmak istemezseniz ve yazdırma deyimlerinizi yeniden yazmak istemezseniz sys.stdout = open(file_name, 'w')başlangıçta bir şeyler yapabilirsiniz .
Zelda

Teşekkürler Zelda. Yardımlarınız için teşekkürler .. Soruyu bazı detaylarla güncelledim .. test.py'imin çalışıp çalışmadığını görmek için bunu yapmaya çalışıyorum .. Çalışıp çalışmadığını göstermiyor .. px ax | grep testing.py.. Bana hiçbir şey döndürmüyor? Neden bir fikrin var mı?
cephanelik

Her şeyi bir try / hariç cümlesine koymalı ve hangi istisnanın üretildiğini ve programın çıkdığını bir günlük dosyasına yazmalısınız. Belki de print cümlesi stdout'a yazamadığı için çalışmıyor.
Zelda

20

Daha fazla kabuk yönelimli bir yaklaşım da alabilirsin. Sizin var crono ölürse o sizin komut dosyası için görünüm ve tekrar başlatın.

  1. Çalıştırarak yeni bir crontab oluşturun crontab -e. Bu, en sevdiğiniz metin editörünün bir penceresini açacaktır.

  2. Bu satırı yeni açılan dosyaya ekle

    */5 * * * * pgrep -f testing.py || nohup python /home/you/scripts/testing.py > test.out
  3. Dosyayı kaydedin ve editörden çıkın.

Az önce crontabher 5 dakikada bir çalışacak yeni bir yazı yarattınız ve senaryoyu zaten çalışmadıkça başlatın. Güzel bir eğitim için buraya bakınız cron. Resmi Ubuntu dokümanlar üzerinde cronbulunmaktadır burada .

Çalıştırılan asıl komut pgrep, komut satırında verilen dizge için çalışan işlemleri arar. pgrep fooadında bir program arayacak foove işlem tanımlayıcısını döndürecektir . pgrep -fYalnızca program adını değil, programı başlatmak için kullanılan komut satırının tamamını aramasını sağlar (çünkü bu bir python betiğidir).

||Sembol aracı "önceki komutu başarısız olursa bunu". Böylece, betiğiniz çalışmıyorsa, pgrephiçbir şey bulamayacağından ve betiğiniz başlatılacağından başarısız olur.


Teşekkürler .. Ama ben linux ve unix için yeniyim bu yüzden crontab'ın nerede olduğunu bilmiyor musunuz? Bu, ubuntu makinemdeki bir yerde bir dosya mı?
arsenal,

@Webby güncellenmiş cevabı gör.
terdon

Thanks terdon .. Bu komutu crontab -epython betiğimin bulunduğu dizinden çalıştırabilirim .. Doğru mu?
arsenal

1
@Webby istediğiniz herhangi bir yerden çalıştırabilirsiniz. cronbir zamanlama arka plan programıdır, arka planda çalışan bir hizmettir. Python betiğinizde değilse $PATH(herhangi bir yerden başlatamazsanız ancak dizinde olması gerekiyorsa), güncelleştirilmiş cevabımdaki gibi betiğin tam yolunu kullanın.
terdon

Teşekkürler. Şimdi mantıklı geliyor .. Ben sadece yeni bir crontab oluşturdum ve aynı tek satır ekleyerek dosyayı düzenledi ama 1 dakika için .. Ben zaten etrafında dönen bir Hello World Python betiği oluşturdum. crontab dosyası, 1 dakika sonra otomatik olarak testing.py dosyasını başlatmalı mı? Ve sonra her 1 dakikada bir python betiğinin çalışıp çalışmadığını kontrol etmeye devam edin. Evet ise, crontab -e dosyasını kaydettikten sonra ps ax | grep testing.py ve bunun için herhangi bir işlem göremiyorum?
cephanelik

6

Test programının çıktısını bir komut satırı seçeneği kullanarak yönlendirmesini ve ardından programı süresiz olarak yeniden başlatmak için basit bir python betiği kullanmasını sağlayabilirsiniz:

import subprocess

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

Bu programı arka plana koyabilirsiniz ve bir kez durdurmak istiyorsanız sadece ön plana çekin ve onu öldürün.


6

Bunu gerçekten üretim için kullanmamalısınız, ancak şunları yapabilirsiniz:

#!/bin/sh

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

Herhangi bir nedenden ötürü, python işlemi sona ererse, kabuk döngüsü devam eder ve .outdosyayı istediğiniz şekilde ekleyerek yeniden başlatır . Neredeyse hiçbir ek yük ve kurmak için çok az zaman alır.


6

UNIX / Linux altındaki süreçleri izlemenin ve yeniden başlatmanın çeşitli yolları vardır. En eskilerden biri, eski SysV init sistemini kullanıyorsanız / etc / inittab ... içindeki "respawn" girişidir. Diğer bir yöntem de DJ Bernstein'ın daemontools paketindeki gözetmen arka planını kullanmaktır . Diğer seçenekler, Ubuntu starttart ... veya systemd veya diğerleri içindeki özellikleri kullanmaktır .

Ancak Pardus: mudur daemon için init ve Python kodundaki alternatiflere bakabilirsiniz .

Bir cron işine (ve PID dosya işleme) gitmeye karar verirseniz, bu PEP 3143'ü okumayı ve belki de referans uygulamasını kullanmayı düşünün .

Diğer yorumlarımda bahsettiğim gibi, sağlam PID dosyası işleme zor. Yarışlara ve köşe davalarına eğilimli. PID dosyanızın NFS veya başka bir ağ bağlantılı dosya sisteminde sona erme ihtimali varsa daha hüzünlü olur (atomikliğin bir kısmı, uygun yerel UNIX / Linux dosya sistemlerinde dosya işleme semantiği ile almanızı garanti eder , NFS'nin bazı sürümlerinde ve uygulamalarında, Örneğin). Ayrıca UNIX altında dosya kilitlemenin etrafındaki anlambilimi de zor olabilir. ( Örneğin, SIGKILL ile tutma işlemi öldürüldüğünde hedef işletim sisteminizde derhal bir flockveya fcntlkilit serbest bırakılıyor mu?).


3

Ayrıca ps-watcher ile monit Or Process'i de kullanabilirsiniz.

Monit, bir UNIX sistemindeki süreçleri, programları, dosyaları, dizinleri ve dosya sistemlerini yönetmek ve izlemek için açık kaynaklı bir yardımcı programdır. Monit, otomatik bakım ve onarım yapar ve hata durumlarında anlamlı nedensel eylemleri gerçekleştirebilir.

İşte senaryonuz için örnek:

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

Monit örneklerine bakın


1

Bir danışman ihtiyaç kullanabilirsiniz danışmanı . Python tabanlı bir süpervizördür, bu nedenle ihtiyacınız olursa değiştirmesi kolaydır.

Kontrol, .ini dosya sözdizimine sahip dosyalarla yapılır.


0

Terdon'ın cevabı, benim için işe yaramadı çünkü pgrep -f testing.pyasla 'başarısız olmadı'. Cron işi için pid kapar (-f seçeneğinden dolayı). Ancak, -f seçeneği olmadan pgrep testing.py dosyasını bulamaz, çünkü testing.py adlı bir işlem yoktur.

Buna benim çözümüm değişmek oldu.

pgrep -f testing.py

için

pgrep -f testing.py | pgrep python

Bu, tam crontab işi olacağı anlamına gelir:

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

0

Benim durumumda, hızlı bir düzeltme olarak, programımın bir hatayla çıktığında veya öldüğünde çalışmasını sağlamak istedim. Diğer taraftan, program doğru bir şekilde sonlandırıldığında yürütmeyi durdurmak istedim (dönüş kodu = 0)

Bash üzerinde test ettim. Başka bir kabuğun içinde iyi çalışması gerekir

#!/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 cevabı için pgrep -f testing.pyde görüşleri doğrultusunda false döndürür asla burada :

Bence sorun şu ki, cron komutunu çalıştırmak için bir kabuk açıyor ve bu kabuğun argümanları, -f kullandığınızdan beri pgrep tarafından eşleştiriliyor.

Matt'in cevabı için, çalışan herhangi bir Python senaryosuyla eşleştiğinden pgrep -f testing.pyberi işe yaramaz pgrep python. Yani iki Python senaryosu cronjob ise, ikinci cronjob asla çalışmayacak.

Sonra pgrep -f testing.pyburadaki yorumda çözülecek çözümü buldum : https://askubuntu.com/questions/1014559/running-pgrep-in-a-crontab?noredirect=1&lq=1

İki Python betiği çalıştırmak için cronum:

* * * * * 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.