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.