Criei uma unidade SystemD para iniciar um serviço e esse serviço requer que outra unidade seja iniciada antecipadamente.
Eu configurei o serviço dependente com Requires=dependant.service
, e dessa forma quando depending.service
é iniciado automaticamente durante a inicialização, ele primeiro tenta iniciar dependant.service
.
O problema é que, se dependant.service
começar muito cedo, falha ao iniciar (não tenho certeza do que significa "muito cedo" aqui). Para resolver isso, configurei dependant.service
para Restart=always
.
E isso funciona bem - depending.service
está habilitado e inicia automaticamente, inicia dependant.service
, que trava e depois é reiniciado e sempre consegue iniciar na 2ª tentativa.
Mas depending.service
vi dependant.service
a primeira falha do 's e suas Requires=dependant.service
causas para falhar. O registro mostra:
systemd[1]: Dependency failed for depending.
systemd[1]: Job depending.service/start failed with result 'dependency'.
Mesmo que dependant
eventualmente tenha sucesso, e ambos tenham Restart=always
, depending
nunca reinicia após a falha inicial de dependant
.
Eu tentei várias configurações de Requires=
, e Wants=
, mas não consegui encontrar uma combinação que causasse a reinicialização após a reinicialização.BindsTo=
After
depending
dependant
Parece que a causa raiz é que
dependant.service
às vezes está começando cedo demais: adicionarRestart
diretivas é um pouco complicado. Isso para mim indica que está faltando um requisito de tempo,After
para o que serve. Dependendo do tipo de serviço, você precisará determinar quais recursos são necessários antes de iniciar o serviço.Supondo que isso esteja relacionado à rede, você desejará adicionar o seguinte na
[Unit]
seção dedependant.service
:Ao fazer isso, você está indicando que a rede básica deve estar disponível antes que o systemd tente iniciar o serviço. Caso contrário, o systemd tentará iniciar o máximo de serviços em paralelo possível, o que significa que, dependendo da ordem de início, você pode iniciar basicamente sem nada inicializado, que é uma situação que alguns serviços podem tolerar e outros falham muito.
Se você quiser ter certeza de que
depending.service
sempre reinicia comdependant.service
, adicione umBindsTo
eAfter
adepending.service
:Esses comportamentos são documentados na
systemd.unit(7)
página de manual. Raramente preciso usar mais deWants
,Requires
eAfter
, mas há opções mais avançadas se você tiver serviços com condições de inicialização particularmente complexas.Acho útil, ao criar um novo serviço (ou grupo de serviços), examinar os arquivos da unidade fornecidos pela distribuição para ver como eles são feitos e copiar descaradamente as partes boas (tente
/usr/lib/systemd/system
ou/lib/systemd/system
): eles geralmente têm pistas sobre o queAfter
eRequires
os requisitos são úteis para um determinado tipo de serviço.Para mim
BindsTo
não ajuda. Isso é (eu acho), porqueBindsTo
significa que a unidade dependente não pode ser executada sem a unidade dependente. Mas nesta situação o processo dependente não foi iniciado porque a unidade dependente falhou ao iniciar pela primeira vez.Mas, de acordo com a documentação da unidade systemd,
PartOf
propaga o evento após cada reinicialização. Então isso funcionou para mim: