Systemd: Как обеспечить повторную попытку службы «oneShot», если в первый раз происходит сбой?

18

Я прочитал man-страницу службы systemd несколько раз, но все еще не могу понять базовый шаблон systemd:

Я хочу запустить процесс запуска один раз (например, Docker-контейнер или отформатировать диск) при загрузке, успешно до завершения. Но если я использую Type = oneshot для этого, то я не могу использовать Restart = on-fail, и если он потерпит неудачу, он не будет повторять работу. Я что-то упускаю здесь очевидное?

Я также попытался установить Type = simple с Restart = on-fail, но во многих случаях мне нужно следующее поведение (из man-страницы), которое предоставляют службы oneshot:

Поведение одних рук похоже на простое; однако ожидается, что процесс должен завершиться до того, как systemd запустит последующие блоки.

Обновления:

JKnight
источник
Один из обходных путей, который я использовал, - это пропустить Restartи обернуть my_cmd так: ExecStart=/bin/sh -c 'while ! my_cmd; do sleep 1; done'вместе с некоторым разумным TimeoutStartSecзначением.
rozcietrzewiacz
Вы смотрели на FailureAction = ? Может быть в состоянии достичь того же, что и Restart=при настройке FailureAction=[self.unit](замените [self.unit] на имя устройства). Это вроде хакерский, но, по крайней мере, явно и достаточно легко следовать.
Сентиман
@Centimane FailureActionпринимает те же значения StartLimitAction, что и все, кроме noneзапуска отключения какого-либо рода.
jpkotta

Ответы:

5

Один из возможных обходных путей, который я пытаюсь

  [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

Где сценарий tag.shбудет touch /ack/TAG_SUCCESSв конце выполнения. Я полагаю, что это довольно близко к желаемому поведению, потому что ExecStartPreбудет последовательно выполняться, ожидая успешного завершения, прежде чем вызов ExecStartи модуль будет считаться только Startingодин раз, ExecStartи к этому моменту мы уверены, что выполнили задачу запуска.

Но это все еще похоже на гигантский взлом?

JKnight
источник
Это работало хорошо для меня, за исключением того, что я также должен был установить, RemainAfterExit=yesчтобы юнит оставался «активным», чтобы другие юниты могли зависеть от него.
Guss