Systemd: Wie kann sichergestellt werden, dass ein OneShot-Dienst wiederholt wird, wenn er das erste Mal fehlschlägt?

17

Ich habe die Manpage zum systemd-Dienst ein paar Mal gelesen, kann aber immer noch kein grundlegendes systemd-Muster herausfinden:

Ich möchte einen einmaligen Startvorgang (wie einen Docker-Container oder das Formatieren eines Laufwerks) beim Booten erfolgreich abschließen. Wenn ich dafür jedoch Type = oneshot verwende, kann ich Restart = on-failure nicht verwenden. Wenn dies fehlschlägt, wird der Auftrag nicht wiederholt. Vermisse ich hier etwas Offensichtliches?

Ich habe auch versucht, Type = simple mit Restart = on-failure zu setzen, aber in vielen Fällen brauche ich das folgende Verhalten (von der Manpage), das die OneShot-Dienste liefern:

Das Verhalten von oneshot ist ähnlich einfach; Es wird jedoch erwartet, dass der Prozess beendet werden muss, bevor systemd Nachfolgeeinheiten startet.

Aktualisierung:

JKnight
quelle
Ein Workaround, den ich verwendet habe, ist das Weglassen Restartund Umbrechen von my_cmd : ExecStart=/bin/sh -c 'while ! my_cmd; do sleep 1; done'zusammen mit einem angemessenen TimeoutStartSecWert.
Rozcietrzewiacz
Haben Sie sich FailureAction = angesehen ? Ist möglicherweise in der Lage, dasselbe zu erreichen wie Restart=durch Einstellen FailureAction=[self.unit](ersetzen Sie [self.unit] durch den Namen des Geräts). Es ist irgendwie abgedreht, aber zumindest explizit und leicht zu befolgen.
Centimane
@Centimane FailureActionnimmt die gleichen Werte an wie StartLimitActionund alle außer nonelösen eine Art Herunterfahren aus.
Jpkotta

Antworten:

5

Eine mögliche Problemumgehung, die ich versuche, ist

  [Unit]
    Description=Tags instance and EBS vols
    After=docker.service
    Requires=docker.service

    [Service]
    ExecStartPre=/usr/bin/docker run --rm -v /opt/tag.sh:/tag.sh -v /opt:/ack --entrypoint=/bin/sh alpine /tag.sh
    ExecStartPre=/usr/bin/sh -c '[[ -e /opt/TAG_SUCCESS ]]'
    ExecStart=/usr/bin/rm /opt/TAG_SUCCESS
    Restart=on-failure
    RestartSec=30

Wo der Skript tag.shWillen touch /ack/TAG_SUCCESSam Ende der Ausführung. Ich glaube, dass dies dem gewünschten Verhalten ziemlich nahe kommt, da ExecStartPrees nacheinander ausgeführt wird und auf den erfolgreichen Abschluss wartet, bevor der Aufruf erfolgt. ExecStartDas Gerät wird nur dann berücksichtigt, Startingwenn der ExecStartAufruf zu dem Zeitpunkt erfolgt ist, zu dem wir sicher sind, dass wir die Startaufgabe abgeschlossen haben.

Aber das fühlt sich immer noch wie ein riesiger Hack an?

JKnight
quelle
Dies funktionierte gut für mich, außer dass ich auch einstellen musste RemainAfterExit=yes, dass die Einheit "aktiv" bleibt, damit andere Einheiten davon abhängen können.
Guss