Chcete-li provést nějaké vyčištění, pokud služba selže, můžete použít ExecStopPost=
, který se provede bez ohledu na to, zda je služba úspěšná nebo ne.
V kódu spustíte na ExecStopPost=
, můžete použít jeden z $SERVICE_RESULT
, $EXIT_CODE
nebo $EXIT_STATUS
určit poruchový stav a podle toho jednat. Podívejte se do dokumentace k těmto proměnným prostředí a zjistěte, která z nich je pro vás vhodná.
Pak můžete použít Restart=on-failure
takže systemd se pokusí restartovat vaši jednotku, když selže.
Když to dáme dohromady, tak by to vypadalo takto. Za předpokladu, že run_program
skončí se stavem 2, kdykoli jsou soubory poškozeny (doufejme, že to můžete přizpůsobit jiným scénářům selhání z dokumentace výše), mělo by to fungovat:
[Service]
ExecStart=/bin/run_program
ExecStopPost=/bin/sh -c 'if [ "$$EXIT_STATUS" = 2 ]; then rm /file/to/delete; fi'
Restart=on-failure
(POZNÁMKA :Dvojitý znak dolaru $$
je to uniknout do systemd, takže shell vidí $EXIT_STATUS
a přistupuje k této proměnné. Použití jediného znaku dolaru by také fungovalo, ale pak by toto nahrazení provedl systemd a shell by viděl [ "2" = 2 ]
, což pravděpodobně také funguje... Většinu z toho můžete obejít tak, že veškerou tuto logiku vložíte do skriptu shellu a zavoláte ji úplnou cestou v ExecStopPost=
, to by bylo pravděpodobně lepší a také byste mohli do skriptu snadno přidat další příkazy, jako je protokolování akce provedené k zotavení z chybového stavu.)
Doufejme, že vám to poskytne dostatek ukazatelů, abyste zjistili, jak to správně nakonfigurovat ve vaší konkrétní situaci!
POZNÁMKA :Pravděpodobně budete chtít použít ExecStopPost=
místo OnFailure=
zde (viz moje další odpověď), ale toto se snaží vyřešit, proč vaše OnFailure=
nastavení nefunguje.
Problém s OnFailure=
nespuštění jednotky může být způsobeno tím, že je ve špatné sekci, musí být v [Unit]
sekce a ne [Service]
.
Místo toho můžete zkusit toto:
# software.service
[Unit]
Description=Software
OnFailure=software-fail.service
[Service]
ExecStart=/bin/run_program
A:
# software-fail.service
[Unit]
Description=Delete corrupt files
[Service]
ExecStart=/bin/rm /file/to/delete
ExecStop=/bin/systemctl --user start software.service
S tímto nastavením to zvládnu.
Všimněte si však, že pomocí OnFailure=
zde není ideální, protože nemůžete skutečně říct, proč program selhal a zřetězení dalšího jeho spuštění v ExecStop=
voláním /bin/systemctl start
přímo je dost hackery... Řešení pomocí ExecStopPost=
a pohled na výstupní stav je rozhodně lepší.
Pokud definujete OnFailure=
uvnitř [Service]
, systemd (alespoň verze 234 z Fedory 27) si stěžuje:
software.service:6: Unknown lvalue 'OnFailure' in section 'Service'
Nejste si jisti, zda to vidíte ve svých protokolech nebo ne... (Možná to bylo přidáno v nedávném systemd?) To by měl být náznak toho, co se tam děje.