Systemd: ¿Cómo asegurar que un servicio de "un disparo" se vuelva a intentar si falla la primera vez?

18

He leído la página de manual del servicio systemd varias veces, pero aún no puedo entender un patrón básico de systemd:

Quiero ejecutar un proceso de inicio una vez (como un contenedor acoplable o formatear una unidad) en el arranque, con éxito hasta su finalización. Pero si uso Type = oneshot para eso, entonces no puedo usar Restart = on-failure, y si falla, no volverá a intentar el trabajo. ¿Me estoy perdiendo algo obvio aquí?

También intenté configurar Type = simple con Restart = on-failure, pero en muchos casos necesito el siguiente comportamiento (de la página de manual) que ofrecen los servicios de onehot:

El comportamiento de oneshot es similar a simple; sin embargo, se espera que el proceso tenga que salir antes de que systemd comience las unidades de seguimiento.

Actualizaciones:

JKnight
fuente
Una solución alternativa que he usado es omitir Restarty envolver my_cmd así: ExecStart=/bin/sh -c 'while ! my_cmd; do sleep 1; done'junto con un TimeoutStartSecvalor razonable .
rozcietrzewiacz
¿Has mirado en FailureAction = ? Es posible que pueda lograr lo mismo que Restart=estableciendo FailureAction=[self.unit](reemplace [self.unit] con el nombre de la unidad). Es algo hacky, pero al menos explícito y fácil de seguir.
Centimane
@Centimane FailureActiontoma los mismos valores que StartLimitAction, y todos excepto nonedesencadenar un cierre de algún tipo.
jpkotta

Respuestas:

5

Una posible solución que estoy intentando es

  [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

Donde la secuencia de comandos tag.shserá touch /ack/TAG_SUCCESSal final de la ejecución. Creo que esto se acerca bastante al comportamiento deseado porque ExecStartPrese ejecutará secuencialmente, esperando la finalización exitosa antes de llamarExecStart y la unidad solo se considera Startinguna vez que ExecStartse llama, momento en el que estamos seguros de que hemos completado la tarea de inicio.

¿Pero esto todavía se siente como un truco gigante?

JKnight
fuente
Esto funcionó bien para mí, excepto que también tuve que configurar RemainAfterExit=yespara que la unidad permanezca "activa" para que otras unidades puedan depender de ella.
Guss