Ponowne uruchomienie systemu = zawsze nie jest honorowane

53

Uwaga: Napisałem artykuł na Medium, który wyjaśnia, jak utworzyć usługę i jak uniknąć tego konkretnego problemu: Tworzenie usługi Linux za pomocą systemd .

Oryginalne pytanie:


Używam systemd, aby skrypt roboczy działał przez cały czas:

[Unit]
Description=My worker
After=mysqld.service

[Service]
Type=simple
Restart=always
ExecStart=/path/to/script

[Install]
WantedBy=multi-user.target

Chociaż restart działa poprawnie, jeśli skrypt zakończy się normalnie po kilku minutach, zauważyłem, że jeśli wielokrotnie nie uruchamia się przy starcie, systemdpo prostu zrezygnuje z próby uruchomienia:

Jun 14 11:10:31 localhost systemd[1]: test.service: Main process exited, code=exited, status=1/FAILURE
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'exit-code'.
Jun 14 11:10:31 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.
Jun 14 11:10:31 localhost systemd[1]: test.service: Start request repeated too quickly.
Jun 14 11:10:31 localhost systemd[1]: Failed to start My worker.
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'start-limit'.

Podobnie, jeśli mój skrypt roboczy kilkakrotnie zawiedzie ze statusem wyjścia 255, systemdrezygnuje z próby jego ponownego uruchomienia:

Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'exit-code'.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Start request repeated too quickly.  
Jun 14 11:25:51 localhost systemd[1]: Failed to start My worker.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Unit entered failed state.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'start-limit'.

Czy istnieje sposób, aby zmusić zawszesystemd do ponownej próby po kilku sekundach?

Benzoes
źródło

Odpowiedzi:

53

Chciałbym trochę rozszerzyć odpowiedź Rahula.

SystemD próbuje ponownie uruchomić wiele razy ( StartLimitBurst) i przestaje próbować, jeśli liczba prób zostanie osiągnięta w ciągu StartLimitIntervalSec. Obie opcje należą do [unit]sekcji.

Domyślne opóźnienie między wykonaniami wynosi 100ms ( RestartSec), co powoduje, że limit prędkości jest osiągany bardzo szybko.

SystemD nie będzie próbował już nigdy żadnych automatycznych restartów dla jednostek ze zdefiniowaną polityką Restart :

Należy zauważyć, że jednostki, które są skonfigurowane Restart=i osiągają limit początkowy, nie są już próbowane ponownie uruchamiać; mogą jednak zostać ponownie uruchomione ręcznie w późniejszym momencie, od tego momentu logika ponownego uruchamiania jest ponownie aktywowana.

Odpowiedź Rahula pomaga, ponieważ dłuższe opóźnienie zapobiega osiągnięciu licznika błędów w StartLimitIntervalSecczasie. Prawidłowa odpowiedź to jednak ustawienie zarówno rozsądnych wartości, jak RestartSeci StartLimitBurstich wartości.

MarSik
źródło
5
Teraz (w końcu) rozumiem, jak to działa, po kilku próbach i błędach widzę, że twoja odpowiedź jest najbardziej poprawna. Konkluzja dla mnie: set StartLimitIntervalSec=0i voilà.
Benjamin
34

Tak jest. Możesz określić, aby spróbować ponownie po xkilku sekundach w [Service]sekcji,

[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/path/to/script

Po zapisaniu pliku należy ponownie załadować konfiguracje demona, aby upewnić się, że systemdjest świadomy nowego pliku,

systemctl daemon-reload

następnie uruchom ponownie usługę, aby umożliwić zmiany,

systemctl restart test

Tak jak prosiłeś, przeglądając dokumentację,

Restart=on-failure

brzmi jak godna rekomendacja.

Rahul
źródło
Wygląda na to, że działa, dziękuję! Aby lepiej to zrozumieć, bez RestartSecdyrektywy, systemdpróby przerwania są bardzo szybko uruchamiane, a następnie przechodzą w stan trwałej awarii; coś, co nie może się zdarzyć, gdy RestartSecjest określone?
Benjamin
Zauważyłem również, że opóźnia to „normalny” restart mojego pracownika (celowo wychodzę z niego z wdziękiem po kilku minutach); czy istnieje sposób, aby opóźnić tylko nieudany restart?
Benjamin
@Benjamin zobacz moje aktualizacje
Rahul
@ Benjamin można sprawdzić tutaj, aby uzyskać więcej parametrów.
Rahul
3
Sądząc po dokumencie , alwaysjest nadzbiorem on-failure, więc to nie pomoże!
Benjamin
4

systemd rezygnuje z próby ponownego uruchomienia

Nie. Systemd rezygnuje z próby ponownego uruchomienia go na chwilę . Widać to wyraźnie w dostarczonym dzienniku:

14 czerwca 11:25:51 localhost systemd [1]: test.service: Błąd wyniku „start-limit” .

To ogranicza tempo wprowadzania.

Długość krótkiego czasu jest określona w jednostce serwisowej, przy użyciu StartLimitIntervalSec=ustawienia. Liczba uruchomień potrzebnych w tym przedziale do uruchomienia mechanizmu ograniczania prędkości jest określana za pomocą StartLimitBurst=ustawienia. Jeśli nic w twoim systemie nie różni się od waniliowego systemd, łącznie z domyślnymi dla tych dwóch ustawień, oznacza to 5 razy w ciągu 10 sekund.

StartLimitIntervalSec=0wyłącza ograniczanie stawek. Ale lepszym podejściem jest sprawienie, aby twoja usługa albo nie wychodziła tak często, albo była wystarczająco bezczynna między wyjściami i restartami, aby nie przekraczała progu ograniczenia prędkości.

Pamiętaj, że ograniczanie stawek nie ma znaczenia, jak Twoja usługa została zakończona. Wywołuje liczbę prób uruchomienia / ponownego uruchomienia, niezależnie od ich przyczyny.

Dalsza lektura

JdeBP
źródło
5
Wydaje się jednak, że poddaje się na stałe: „Aktywny: nieudany (Wynik: limit startowy) od śro 2016-06-15 01:21:24 CEST; 12 godzin temu”. Pozostaje w tym stanie, a skrypt nigdy nie jest wykonywany ponownie. Próbowałem ustawić ręcznie StartLimitIntervalSec=10i StartLimitIntervalSec=5bez powodzenia.
Benjamin,
4
Domyślnie poddaje się na stałe. Zobacz github.com/systemd/systemd/issues/2416 .
Adam Goode
2
Konkluzja: aby zatrzymać, aby nie poddać się na stałe, ustaw StartLimitIntervalSec=0.
Benjamin