Um eine Bereinigung durchzuführen, wenn der Dienst fehlschlägt, können Sie ExecStopPost=
verwenden , die unabhängig davon ausgeführt wird, ob der Dienst erfolgreich ist oder nicht.
Im Code, den Sie bei ExecStopPost=
ausführen , können Sie einen von $SERVICE_RESULT
verwenden , $EXIT_CODE
oder $EXIT_STATUS
um den Fehlerzustand zu bestimmen und entsprechend zu handeln. Sehen Sie in der Dokumentation zu diesen Umgebungsvariablen nach, um zu prüfen, welche für Sie geeignet ist.
Dann können Sie Restart=on-failure
verwenden damit systemd versucht, Ihr Gerät neu zu starten, wenn es fehlschlägt.
Alles zusammengenommen würde es so aussehen. Angenommen, run_program
wird mit Status 2 beendet, wenn die Dateien beschädigt sind (hoffentlich können Sie dies an andere Fehlerszenarien aus der obigen Dokumentation anpassen), dies sollte funktionieren:
[Service]
ExecStart=/bin/run_program
ExecStopPost=/bin/sh -c 'if [ "$$EXIT_STATUS" = 2 ]; then rm /file/to/delete; fi'
Restart=on-failure
(HINWEIS :Das doppelte Dollarzeichen $$
ist, dies an systemd zu maskieren, damit die Shell $EXIT_STATUS
sieht und greift auf diese Variable zu. Die Verwendung eines einzelnen Dollarzeichens würde auch funktionieren, aber dann würde systemd stattdessen diese Ersetzung vornehmen und die Shell würde [ "2" = 2 ]
sehen , was wohl auch funktioniert ... Wie auch immer, Sie können das meiste davon umgehen, indem Sie all diese Logik in ein Shell-Skript einfügen und es mit seinem vollständigen Pfad in ExecStopPost=
aufrufen , das wäre wahrscheinlich besser und Sie könnten dem Skript auch problemlos weitere Befehle hinzufügen, z
Hoffentlich gibt Ihnen dies genügend Hinweise, um herauszufinden, wie Sie dies in Ihrer speziellen Situation richtig konfigurieren können!
HINWEIS :Wahrscheinlich möchten Sie ExecStopPost=
verwenden statt OnFailure=
hier (siehe meine andere Antwort), aber dies versucht zu erklären, warum Ihr OnFailure=
Setup funktioniert nicht.
Das Problem mit OnFailure=
Das Gerät kann nicht gestartet werden, weil es im falschen Abschnitt ist, es muss in [Unit]
sein Abschnitt und nicht [Service]
.
Sie können stattdessen Folgendes versuchen:
# software.service
[Unit]
Description=Software
OnFailure=software-fail.service
[Service]
ExecStart=/bin/run_program
Und:
# software-fail.service
[Unit]
Description=Delete corrupt files
[Service]
ExecStart=/bin/rm /file/to/delete
ExecStop=/bin/systemctl --user start software.service
Ich kann es mit diesem Setup zum Laufen bringen.
Beachten Sie jedoch, dass die Verwendung von OnFailure=
ist hier nicht ideal, da Sie nicht wirklich sagen können, warum das Programm fehlgeschlagen ist, und einen weiteren Start davon in ExecStop=
zu verketten durch Aufruf von /bin/systemctl start
direkt ist ziemlich hacky... Die Lösung mit ExecStopPost=
und der Blick auf den Exit-Status ist definitiv besser.
Wenn Sie OnFailure=
definieren innerhalb von [Service]
, systemd (mindestens Version 234 von Fedora 27) beschwert sich mit:
software.service:6: Unknown lvalue 'OnFailure' in section 'Service'
Ich bin mir nicht sicher, ob Sie das in Ihren Protokollen sehen oder nicht ... (Vielleicht wurde dies kürzlich in systemd hinzugefügt?) Das sollte ein Hinweis darauf sein, was dort vor sich geht.