Systemd: Comment garantir qu'un service «one-shot» sera retenté s'il échoue la première fois?

18

J'ai lu la page de manuel du service systemd à quelques reprises, mais je n'arrive toujours pas à comprendre un modèle de base systemd:

Je veux exécuter un processus de démarrage une fois (comme un conteneur Docker ou formater un lecteur) au démarrage, avec succès jusqu'à la fin. Mais si j'utilise Type = oneshot pour cela, je ne peux pas utiliser Restart = en cas d'échec, et s'il échoue, il ne recommencera pas le travail. Suis-je en train de manquer quelque chose d'évident ici?

J'ai également essayé de définir Type = simple avec Restart = on-failure, mais cela dans de nombreux cas, j'ai besoin du comportement suivant (à partir de la page de manuel) que les services oneshot donnent:

Le comportement de one-shot est similaire à simple; cependant, il est prévu que le processus doit se terminer avant que systemd ne démarre les unités de suivi.

Mises à jour:

JKnight
la source
Une solution de contournement que j'ai utilisée consiste à omettre Restartet à boucler my_cmd comme ceci ExecStart=/bin/sh -c 'while ! my_cmd; do sleep 1; done':, avec une TimeoutStartSecvaleur raisonnable .
rozcietrzewiacz
Avez-vous regardé FailureAction = ? Pourrait être en mesure de réaliser la même chose qu'en Restart=définissant FailureAction=[self.unit](remplacer [self.unit] par le nom de l'unité). C'est un peu hacky, mais au moins explicite et assez facile à suivre.
Centimane
@Centimane FailureActionprend les mêmes valeurs que StartLimitAction, et tous sauf nonedéclencher un arrêt quelconque.
jpkotta

Réponses:

5

Une solution possible que j'essaie est

  [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

Où le script tag.shsera touch /ack/TAG_SUCCESSà la fin de l'exécution. Je crois que cela se rapproche assez du comportement souhaité, car ExecStartPreil s'exécutera séquentiellement, en attendant la fin réussie avant d'appeler ExecStartet l'unité n'est prise en compte qu'une Startingfois ExecStartappelée, à quel point nous sommes sûrs d'avoir terminé la tâche de démarrage.

Mais cela ressemble toujours à un hack géant?

JKnight
la source
Cela a bien fonctionné pour moi, sauf que j'ai également dû régler RemainAfterExit=yespour que l'unité reste "active" afin que les autres unités puissent en dépendre.
Guss