Mam skrypt w języku Python, który sprawdza kolejkę i wykonuje akcję na każdym elemencie:
# checkqueue.py
while True:
check_queue()
do_something()
Jak napisać skrypt bash, który sprawdzi, czy jest uruchomiony, a jeśli nie, uruchom go. Z grubsza następujący pseudo kod (a może powinien zrobić coś takiego ps | grep
?):
# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
Nazwie to od crontab:
# crontab
*/5 * * * * /path/to/keepalivescript.sh
Odpowiedzi:
Unikaj plików PID, cronów lub czegokolwiek innego, co próbuje ocenić procesy, które nie są ich dziećmi.
Istnieje bardzo dobry powód, dla którego w UNIX możesz TYLKO czekać na swoje dzieci. Każda metoda (ps parsowanie, pgrep, przechowywanie PID, ...), która próbuje obejść tę wadę i ma luki w niej. Po prostu powiedz nie .
Zamiast tego potrzebujesz procesu, który monitoruje proces, aby był jego rodzicem. Co to znaczy? Oznacza to, że tylko proces, który rozpoczyna proces, może niezawodnie czekać na jego zakończenie. W bashu jest to absolutnie trywialne.
Powyższy fragment kodu bash działa
myserver
wuntil
pętli. Pierwsza linia zaczyna sięmyserver
i czeka na zakończenie. Po zakończeniuuntil
sprawdza status wyjścia. Jeśli status wyjścia to0
, oznacza to, że zakończył się z wdziękiem (co oznacza, że poprosiłeś go o zamknięcie i udało się to pomyślnie). W takim przypadku nie chcemy go ponownie uruchamiać (poprosiliśmy tylko o zamknięcie!). Jeśli status wyjścia nie jest0
,until
uruchomi ciało pętli, które emituje komunikat o błędzie na STDERR i ponownie uruchamia pętlę (powrót do linii 1) po 1 sekundzie .Dlaczego czekamy sekundę? Ponieważ jeśli coś jest nie tak z sekwencją uruchamiania
myserver
i natychmiast ulega awarii, będziesz mieć bardzo intensywną pętlę ciągłego restartowania i awarii na rękach. Odciążasleep 1
to od tego napięcia.Teraz wszystko, co musisz zrobić, to uruchomić ten skrypt bash (prawdopodobnie asynchronicznie), a on będzie go monitorował
myserver
i restartował w razie potrzeby. Jeśli chcesz uruchomić monitor przy rozruchu (dzięki czemu serwer „przetrwa” ponowne uruchomienie), możesz zaplanować go w cronie użytkownika (1) z@reboot
regułą. Otwórz swoje reguły cron za pomocącrontab
:Następnie dodaj regułę, aby uruchomić skrypt monitorowania:
Alternatywnie; spójrz na inittab (5) i / etc / inittab. Możesz dodać tam linię, aby
myserver
zacząć od określonego poziomu inicjacji i automatycznie się odradzać.Edytować.
Pozwól, że dodam kilka informacji o tym, dlaczego nie używać plików PID. Chociaż są bardzo popularne; są również bardzo wadliwe i nie ma powodu, dla którego nie zrobiłbyś tego po prostu we właściwy sposób.
Rozważ to:
Recykling PID (zabicie niewłaściwego procesu):
/etc/init.d/foo start
: startfoo
, zapiszfoo
PID do/var/run/foo.pid
foo
jakoś umiera.bar
), przyjmuje losowy PID, wyobraź sobie, że bierze onfoo
stary PID.foo
, że zniknął:/etc/init.d/foo/restart
czyta/var/run/foo.pid
, sprawdza, czy nadal żyje, znajdujebar
, myśli, że tofoo
zabija, zaczyna nowefoo
.Pliki PID stają się nieaktualne. Potrzebujesz nadmiernie skomplikowanej (lub powinienem powiedzieć, nietrywialnej) logiki, aby sprawdzić, czy plik PID jest nieaktualny i czy taka logika jest ponownie podatna na atak
1.
.Co jeśli nie masz dostępu do zapisu lub jesteś w środowisku tylko do odczytu?
To bezcelowa nadmierna komplikacja; zobacz, jak prosty jest mój przykład powyżej. W ogóle nie trzeba tego komplikować.
Zobacz także: Czy pliki PID są nadal wadliwe, gdy robią to „dobrze”?
Tak poza tym; nawet gorzej niż parsowanie plików PID
ps
! Nigdy tego nie rób.ps
jest bardzo nieprzenośny. Chociaż można go znaleźć w prawie każdym systemie UNIX; jego argumenty są bardzo różne, jeśli chcesz otrzymać niestandardowe dane wyjściowe. A standardowe wyjście jest WYŁĄCZNIE do spożycia przez ludzi, a nie do analizowania skryptów!ps
prowadzi do wielu fałszywych trafień. Weźmyps aux | grep PID
przykład, a teraz wyobraźmy sobie, że ktoś zaczyna gdzieś proces z liczbą jako argumentem, który akurat jest taki sam jak PID, którym patrzyłeś na swojego demona! Wyobraź sobie, że dwie osoby rozpoczynają sesję X, a ty żartujesz, że X zabija twoją. To tylko wszelkiego rodzaju złe.Jeśli nie chcesz sam zarządzać procesem; istnieje kilka doskonale dobrych systemów, które będą działać jako monitor twoich procesów. Zobacz na przykład runit .
źródło
while true; do myprocess; done
ale należy pamiętać, że nie ma już sposobu, aby zatrzymać proces.trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; done
Spójrz na monit ( http://mmonit.com/monit/ ). Obsługuje uruchamianie, zatrzymywanie i ponowne uruchamianie skryptu i może przeprowadzać kontrole kondycji oraz restartować w razie potrzeby.
Lub wykonaj prosty skrypt:
źródło
Najłatwiej to zrobić za pomocą flokowania w pliku. Zrobiłbyś to w skrypcie Python
W powłoce możesz faktycznie przetestować, czy działa:
Ale oczywiście nie musisz testować, ponieważ jeśli jest już uruchomiony i uruchomisz go ponownie, zakończy działanie
'other instance already running'
Kiedy proces umiera, wszystkie jego deskryptory plików są zamykane, a wszystkie blokady są automatycznie usuwane.
źródło
flock
... w rzeczywistości strona podręcznika wyraźnie pokazuje, jak!exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd"
to odpowiednik bash dla Twojego Pythona i pozostawia blokadę wstrzymaną (więc jeśli wykonasz proces, blokada pozostanie zablokowana, dopóki proces się nie zakończy).flock
jest poprawne, ale twoje skrypty są nieprawidłowe. Jedyne polecenie, które musisz ustawić w crontab, to:flock -n /tmp/script.lock -c '/path/to/my/script.py'
Powinieneś użyć monit, standardowego narzędzia uniksowego, które może monitorować różne rzeczy w systemie i odpowiednio reagować.
Z dokumentacji: http://mmonit.com/monit/documentation/monit.html#pid_testing
Możesz także skonfigurować monit tak, aby wysyłał Ci e-maile po ponownym uruchomieniu.
źródło
źródło
ps ax|grep ...
. Możesz po prostu zainstalować lub napisać dla tego funkcję: function psgrep () {ps ax | grep -v grep | grep -q "$ 1"}Nie jestem pewien, jak przenośny jest w różnych systemach operacyjnych, ale możesz sprawdzić, czy twój system zawiera polecenie „run-one”, tj. „Man run-one”. W szczególności ten zestaw poleceń obejmuje „ciągłe uruchamianie”, co wydaje się być dokładnie tym, czego potrzeba.
Ze strony podręcznika:
Uwaga: oczywiście można to wywoływać z poziomu skryptu, ale także eliminuje potrzebę posiadania skryptu.
źródło
Z wielkim sukcesem zastosowałem następujący skrypt na wielu serwerach:
uwagi:
$INSTALLATION
zawiera dość ścieżki procesu, co jest całkowicie jednoznaczneTen skrypt jest w rzeczywistości używany do zamykania działającej instancji tomcat, którą chcę zamknąć (i poczekać) w linii poleceń, więc uruchomienie go jako procesu potomnego po prostu nie jest dla mnie opcją.
źródło
grep | awk
wciąż jest antypatternem - chcesz połączyćawk "/$INSTALLATION/ { print \$1 }"
bezużytecznegrep
ze skryptem Awk, który potrafi bardzo dobrze znajdować wiersze poprzez wyrażenie regularne, dziękuję bardzo.Używam tego do mojego procesu npm
źródło