Systemd: Como garantir que um serviço "oneshot" seja tentado novamente se falhar na primeira vez?

17

Eu li a página de manual do serviço systemd algumas vezes, mas ainda não consigo descobrir um padrão básico do systemd:

Desejo executar um processo de inicialização uma vez (como um contêiner de docker ou formatar uma unidade) na inicialização, com êxito até a conclusão. Mas se eu usar Type = oneshot para isso, não posso usar Restart = on-fail e, se falhar, não tentará novamente o trabalho. Estou perdendo algo óbvio aqui?

Eu também tentei definir Type = simple com Restart = on-fail, mas isso em muitos casos eu preciso do seguinte comportamento (da página de manual) que os serviços oneshot oferecem:

O comportamento do oneshot é semelhante ao simples; no entanto, espera-se que o processo precise sair antes que o systemd inicie as unidades de acompanhamento.

Atualizações:

JKnight
fonte
Uma solução alternativa que usei é omitir Restarte agrupar my_cmd desta forma: ExecStart=/bin/sh -c 'while ! my_cmd; do sleep 1; done'junto com algum TimeoutStartSecvalor razoável .
rozcietrzewiacz
Você já viu FailureAction = ? Pode conseguir o mesmo que a Restart=configuração FailureAction=[self.unit](substitua [self.unit] pelo nome da unidade). É meio hacky, mas pelo menos explícito e fácil de seguir.
Centimane
O @Centimane FailureActionaceita os mesmos valores que StartLimitAction, e todos, exceto noneacionar um desligamento de algum tipo.
Jspkotta #

Respostas:

5

Uma possível solução alternativa que estou tentando é

  [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

Onde o script tag.shestará touch /ack/TAG_SUCCESSno final da execução. Acredito que isso se aproxime bastante do comportamento desejado, porque ExecStartPreserá executado sequencialmente, aguardando a conclusão bem-sucedida antes da chamada ExecStarte a unidade será considerada apenas uma Startingvez que ExecStartfor chamada e nesse ponto, temos certeza de que concluímos a tarefa de inicialização.

Mas isso ainda parece um hack gigante?

JKnight
fonte
Isso funcionou bem para mim, exceto que eu também precisei definir RemainAfterExit=yespara que a unidade permanecesse "ativa" para que outras unidades pudessem depender dela.
Guss