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.
until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
Powyższy fragment kodu bash działa myserver
w until
pętli. Pierwsza linia zaczyna się myserver
i czeka na zakończenie. Po zakończeniu until
sprawdza status wyjścia. Jeśli status wyjścia to 0
, 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 jest 0
, 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ąża sleep 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
:
crontab -e
Następnie dodaj regułę, aby uruchomić skrypt monitorowania:
@reboot /usr/local/bin/myservermonitor
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
: start foo
, zapisz foo
PID do/var/run/foo.pid
- Chwilę później:
foo
jakoś umiera.
- Chwilę później: każdy losowy proces, który się rozpoczyna (nazwij go
bar
), przyjmuje losowy PID, wyobraź sobie, że bierze on foo
stary PID.
- Zauważyłeś
foo
, że zniknął: /etc/init.d/foo/restart
czyta /var/run/foo.pid
, sprawdza, czy nadal żyje, znajduje bar
, myśli, że to foo
zabija, zaczyna nowe foo
.
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!
- Parsowanie
ps
prowadzi do wielu fałszywych trafień. Weźmy ps 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 .