Systemd Restart = sempre não é respeitado

54

Nota: escrevi um artigo no Medium que explica como criar um serviço e como evitar esse problema específico: Criando um serviço Linux com o systemd .

Pergunta original:


Estou usando o systemd para manter um script de trabalho funcionando o tempo todo:

[Unit]
Description=My worker
After=mysqld.service

[Service]
Type=simple
Restart=always
ExecStart=/path/to/script

[Install]
WantedBy=multi-user.target

Embora a reinicialização funcione bem se o script sair normalmente após alguns minutos, notei que, se repetidamente falhar na execução na inicialização, systemddesistirá de tentar iniciá-lo:

Jun 14 11:10:31 localhost systemd[1]: test.service: Main process exited, code=exited, status=1/FAILURE
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'exit-code'.
Jun 14 11:10:31 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.
Jun 14 11:10:31 localhost systemd[1]: test.service: Start request repeated too quickly.
Jun 14 11:10:31 localhost systemd[1]: Failed to start My worker.
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'start-limit'.

Da mesma forma, se meu script de trabalho falhar várias vezes com um status de saída 255, systemddesiste de tentar reiniciá-lo:

Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'exit-code'.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Start request repeated too quickly.  
Jun 14 11:25:51 localhost systemd[1]: Failed to start My worker.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Unit entered failed state.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'start-limit'.

Existe uma maneira de forçar systemda sempre tentar novamente após alguns segundos?

Benjamin
fonte

Respostas:

53

Eu gostaria de estender um pouco a resposta de Rahul.

O SystemD tenta reiniciar várias vezes ( StartLimitBurst) e pára de tentar se a contagem de tentativas for alcançada dentro StartLimitIntervalSec. Ambas as opções pertencem à [unit]seção.

O atraso padrão entre execuções é 100ms ( RestartSec), o que faz com que o limite de taxa seja atingido muito rapidamente.

O SystemD não tentará mais reinicializações automáticas para unidades com a política Reiniciar definida :

Observe que as unidades configuradas Restart=e que atingem o limite de partida não tentam mais ser reiniciadas; no entanto, eles ainda podem ser reiniciados manualmente em um momento posterior, a partir desse momento, a lógica de reinicialização é novamente ativada.

A resposta de Rahul ajuda, porque o atraso mais longo impede atingir o contador de erros dentro do StartLimitIntervalSectempo. A resposta correta é definir valores tanto RestartSece StartLimitBurstrazoáveis.

MarSik
fonte
5
Agora que (finalmente) entendi como funciona, depois de alguma tentativa e erro, posso ver que sua resposta é a mais correta. Bottom line para mim: definir StartLimitIntervalSec=0e voilà.
Benjamin
35

Sim existe. Você pode especificar tentar novamente após xsegundos na [Service]seção

[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/path/to/script

Depois de salvar o arquivo, você precisa recarregar as configurações do daemon para garantir o systemdconhecimento do novo arquivo,

systemctl daemon-reload

reinicie o serviço para ativar as alterações,

systemctl restart test

Como você solicitou, Examinando a documentação,

Restart=on-failure

parece uma recomendação decente.

Rahul
fonte
Parece funcionar mesmo, obrigado! Portanto, para entender isso melhor, sem uma RestartSecdiretiva, as systemdtentativas de reinicialização muito rápidas e entram em um estado de falha permanente; algo que não pode acontecer quando RestartSecé especificado?
Benjamin
Além disso, notei que isso atrasa o reinício "normal" do meu trabalhador (estou saindo propositadamente do trabalhador normalmente após alguns minutos); existe uma maneira de atrasar apenas uma falha na reinicialização?
Benjamin
@Benjamin see my updates
Rahul
@ Benjamin você pode conferir aqui para mais parâmetros.
Rahul
3
A julgar pelo documento , alwaysé um superconjunto de on-failure, portanto, não ajudará!
Benjamin
5

systemd desiste de tentar reiniciá-lo

Não. O systemd desiste de tentar reiniciá-lo por um tempo . Isso é mostrado claramente no log que você fornece:

14 de junho 11:25:51 localhost systemd [1]: test.service: falha com o resultado 'start-limit' .

Isso é uma limitação da taxa de entrada.

A duração do pouco tempo é especificada na unidade de serviço, usando a StartLimitIntervalSec=configuração O número de partidas necessárias dentro desse intervalo para acionar o mecanismo de limitação de taxa é especificado através da StartLimitBurst=configuração. Se nada no seu sistema diferir do vanilla systemd, incluindo os padrões dessas duas configurações, serão 5 vezes em 10 segundos.

StartLimitIntervalSec=0desabilita a limitação de taxa, para que o systemd tente novamente para sempre, em vez de desistir. Mas tornar seu serviço ou não sair com tanta frequência ou inativo o suficiente entre saídas e reinicializações para que não exceda o limite de limitação de taxa, é uma abordagem melhor.

Observe que a limitação da taxa não se importa com a saída do serviço. Ele dispara no número de tentativas de iniciá-lo / reiniciá-lo, independentemente de sua causa.

Leitura adicional

JdeBP
fonte
5
Parece desistir permanentemente: "Ativo: falhou (resultado: limite de início) desde quarta-feira 15/06/2016 01:21:24 CEST; há 12h". Ele permanece nesse estado e o script nunca é executado novamente. Eu tentei configurar manualmente StartLimitIntervalSec=10e StartLimitIntervalSec=5, sem sorte.
Benjamin
5
Desiste permanentemente por padrão. Consulte github.com/systemd/systemd/issues/2416 .
22617 Adam Goode
2
Conclusão: para impedir que ele desista permanentemente, defina StartLimitIntervalSec=0.
Benjamin