Como configurar o systemd para matar e reiniciar um daemon ao recarregar?

12

Eu tenho um daemon da velha escola que quero controlar usando o systemd. Quando o arquivo de configuração é alterado, ele precisa ser eliminado e reiniciado. Em outras palavras, depois de editar o arquivo de configuração, systemctl reload MYSERVICEdeve interromper o processo e reiniciá-lo.

Tentativa 1: tente os padrões. Isso diz ao systemd como iniciar o daemon, mas não como recarregá-lo.

[Service]
ExecStart=/usr/bin/MYSERVICE
Type=simple

Como resultado, starte restarttrabalho, mas reloaddá este erro:

# systemctl reload MYSERVICE
Failed to reload MYSERVICE.service: Job type reload is not applicable for unit MYSERVICE.service.

Tentativa 2: Diga como matar o processo. Isso mata o processo, mas o systemd não o reinicia para mim.

[Service]
ExecStart=/usr/bin/MYSERVICE
Type=simple
ExecReload=/bin/kill -HUP $MAINPID

...Seguido por...

# systemctl daemon-reload
# systemctl reload MYSERVICE

... mata o processo, mas ele não é reiniciado automaticamente.

Tentativa 3: Use ExecReload para reiniciar o processo também. Isso falha por alguns motivos:

ExecReload=/bin/kill -HUP $MAINPID ; /usr/bin/MYSERVICE

... a mensagem de erro recebida ...:

# systemctl daemon-reload
# systemctl reload MYSERVICE
Job for MYSERVICE.service failed because the control process exited with error code. See "systemctl status MYSERVICE.service" and "journalctl -xe" for details.

Eu esperaria que houvesse um ReloadType = kill_and_restart ou algo assim, mas sem essa sorte.

Como dizer ao systemd para matar e reiniciar um daemon ao recarregar?

TomOnTime
fonte
Isso realmente precisa ser calçado para recarregar , onde não se encaixa exatamente? Você não pode fazer o daemon se comportar de maneira sensata?
Michael Hampton
Obrigado @MichaelHampton, mas não é uma situação em que posso reescrever o programa. Agradeço sua sugestão útil. Dito isso, tenho certeza de que este é um caso de uso comum do sistema e uma resposta canônica pode ajudar muitas pessoas.
TomOnTime 31/03
1
Tenho certeza de que uma resposta pode ajudar alguém, então eu votei na pergunta. Só não tenho certeza se esse é um caso de uso comum. Tendo usado o systemd por cinco anos ou mais, quase desde o dia em que foi lançado no mundo, é a primeira vez que me lembro de ouvir sobre alguém tentando esse tipo de cenário. É possível que eu esteja entendendo algo errado por causa da falta de detalhes.
Michael Hampton

Respostas:

16

A resposta é "você não"! Mas temos boas notícias.

A filosofia do systemd é que o recarregamento é opcional e deve ser deixado indefinido se não houver uma funcionalidade de recarregamento verdadeira. Eu definiria "funcionalidade de recarga verdadeira" como uma recarga que não mata e reinicia o serviço ou faz com que o serviço altere seu PID. Em outras palavras, o systemd quer apenas refletir quais recursos existem.

Em vez disso, você deve usar o systemctl reload-or-restartque fará uma recarga, se existir, e uma reinicialização, se não existir.

Na página do manual ...

   reload-or-restart PATTERN...
       Reload one or more units if they support it. If not, restart them
       instead. If the units are not running yet, they will be started.

   reload-or-try-restart PATTERN...
       Reload one or more units if they support it. If not, restart them
       instead. This does nothing if the units are not running. Note that,
       for compatibility with SysV init scripts, force-reload is
       equivalent to this command.

Portanto: (1) deixe ExecReload em branco, (2) use systemctl reload-or-restart MYSERVICEe, (3) você deve estar pronto.

Se você tentar usar o ExecReload para definir uma maneira de matar e reiniciar o serviço, ele terá um novo PID e o systemd ficaria confuso.

TomOnTime
fonte
3

A filosofia do systemd é que reloadé opcional e o usuário do systemd deve saber, para cada serviço, se deve ligar reloadou fingir ligando restart.

Portanto, a resposta para sua pergunta é: "Não funciona e não deveria. Por favor, resolva isso na próxima camada superior".

Em outras palavras, o systemd deseja que você implemente " recarregar " apenas se o serviço subjacente suportar uma verdadeira funcionalidade de recarregamento ... ou seja, um recarregamento que não elimine e reinicie o serviço ou faça com que o serviço altere seu PID. Em outras palavras, o systemd quer apenas refletir quais recursos existem.

Você pode estar se perguntando: Mas não seria mais fácil se eu pudesse implementar uma recarga "falsa" permitindo ExecReloadmatar e reiniciar o serviço? Então eu poderia usar systemctl reload FOOpara todos os meus serviços e não precisaria lembrar quais os suportam e quais não?

Sim, isso seria mais fácil, mas não seria o caminho do systemd. Systemd quer que o chamador seja o que sabe se reloadexiste para o serviço. O Systemd quer ser uma interface comum para os recursos existentes, não quer ser responsável por preencher as lacunas.

Por exemplo, o fantoche pressupõe que um serviço orientado a systemd não possui reloade o padrão é matar e reiniciar o processo . Se o tipo Serviço [] adicionou uma maneira de especificar que a recarga existe e que deve ser usada na notificação, será necessário saber quais serviços têm ou não uma recarga nativa. O Chef e todos os outros sistemas também precisariam aprender a mesma coisa, porque o systemd deseja que ele seja resolvido nessa camada. (MiniRant: para iniciar um processo, o sistema parece ser o sistema eu-tudo-na-minha-camada-que-tudo-sabe-tudo-que-personaliza, tudo-sobre-namespace, portanto, não posso dizer por que não estender essa filosofia para recarregar. Talvez um dos autores possa falar aqui.)

TomOnTime
fonte
1
Existe systemctl reload-or-restart, o que recarregará o serviço se ele for compatível e o reiniciará se não for. Não faço ideia por que Puppet faz essa suposição.
Michael Hampton