Estou usando um arquivo de unidade systemd para controlar um processo python em execução em um servidor (com systemd v247).
Este processo deve ser reiniciado 60 segundos após sua saída, seja em caso de falha ou sucesso, exceto se falhar 5 vezes em 600 segundos.
Este arquivo de unidade vincula outro serviço para notificar falhas por e-mail.
/etc/systemd/system/python-test.service
[Unit]
After=network.target
OnFailure=mailer@%n.service
[Service]
Type=simple
ExecStart=/home/debian/tmp.py
# Any exit status different than 0 is considered as an error
SuccessExitStatus=0
StandardOutput=append:/var/log/python-test.log
StandardError=append:/var/log/python-test.log
# Always restart service 60sec after exit
Restart=always
RestartSec=60
# Stop restarting service after 5 consecutive fail in 600sec interval
StartLimitInterval=600
StartLimitBurst=5
[Install]
WantedBy=multi-user.target
/etc/systemd/system/[email protected]
[Unit]
After=network.target
[Service]
Type=oneshot
ExecStart=/home/debian/mailer.py --to "[email protected]" --subject "Systemd service %I failed" --message "A systemd service failed %I on %H"
[Install]
WantedBy=multi-user.target
O acionamento de OnFailure
funcionou muito bem durante o teste básico. No entanto, quando adicionei a seção a seguir ao arquivo da unidade, ela OnFailure
foi acionada apenas quando as 5 falhas consecutivas ocorreram.
StartLimitInterval=600
StartLimitBurst=5
Este não é o comportamento que eu gostaria, pois quero ser notificado sempre que o processo falhar, mesmo que o limite de burst ainda não tenha sido atingido.
Ao verificar o status do processo, a saída não é a mesma quando o limite de rajada não é atingido
● python-test.service
Loaded: loaded (/etc/systemd/system/python-test.service; disabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Thu 2022-12-22 19:51:23 UTC; 2s ago
Process: 1421600 ExecStart=/home/debian/tmp.py (code=exited, status=1/FAILURE)
Main PID: 1421600 (code=exited, status=1/FAILURE)
CPU: 31ms
Dec 22 19:51:23 test-vps systemd[1]: python-test.service: Failed with result 'exit-code'.
Do que quando é
● python-test.service
Loaded: loaded (/etc/systemd/system/python-test.service; disabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2022-12-22 19:52:02 UTC; 24s ago
Process: 1421609 ExecStart=/home/debian/tmp.py (code=exited, status=1/FAILURE)
Main PID: 1421609 (code=exited, status=1/FAILURE)
CPU: 31ms
Dec 22 19:51:56 test-vps systemd[1]: python-test.service: Failed with result 'exit-code'.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Scheduled restart job, restart counter is at 5.
Dec 22 19:52:02 test-vps systemd[1]: Stopped python-test.service.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Start request repeated too quickly.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Failed with result 'exit-code'.
Dec 22 19:52:02 test-vps systemd[1]: Failed to start python-test.service.
Dec 22 19:52:02 test-vps systemd[1]: python-test.service: Triggering OnFailure= dependencies.
Não consegui encontrar nada explicando como modificar o acionamento de OnFailure
dentro do arquivo da unidade.
Existe uma maneira de notificar os e-mails sempre que o processo falhar e ainda manter o limite de rajada?
Há várias coisas que você deve fazer para trabalhar com o serviço do sistema como deseja (as alterações estão em /etc/systemd/system/python-test.service ).
Restart=always
paraRestart=on-failure
StartLimitInterval=600
,StartLimitBurst=5
parecem ser suportados ainda. No entanto, você deve colocá-los em[Unit]
. Se você colocarStartLimitInterval
,[Unit]
você pode renomeá-lo paraStartLimitIntervalSec
(man systemd.unit
usaStartLimitIntervalSec
em vez disso).RemainAfterExit=no
na[Service]
seção.[Service]
seção:TimeoutStopSec=infinity
EXIT_STATUS
no script para determinar se o script foi encerrado com êxito ou não.OnFailure=mailer@%n.service
paraOnFailure=mailer@%N.service
. A diferença entre ambos é que o uso%N
removerá o sufixo.atd
(sudo systemctl start atd.service
) para poder usarat
o comando. Ou, se você não quiser usarat
, poderá escrever outro serviço systemd para reiniciar o serviço. (neste exemplo, eu useirelaunch.service
)sleep
eRestartSec
. No seu caso, poisRestartSec
tem60
então nessa linha o sleep deve ter60
também:ExecStart
eExecStopPost=
para obter o ExitStatus do seu processo principal:/home/debian/tmp.py
. Não useExecStop
,deman systemd.service
:O serviço /etc/systemd/system/python-test.service deve ser:
E /home/debian/bin/checkSuccess deve ter isto:
Solução 1: Usando
at
o comando:Solução 2: Usando outro serviço systemd:
E o
relaunch.service
deve ter:A
"$EXIT_STATUS"
variável definida pelo serviço systemd é determinada pelo status de saída de/home/debian/tmp.py
.O
${1}
representa o nome da unidade:python-test
e é passado para o script na linha/home/debian/bin/checkSuccess "%N"
.Notas:
'echo The Service %n has exited with values: $$EXIT_STATUS,$$SERVICE_RESULT,$$EXIT_CODE'
em tempo real usando:relaunch.service
) quando quiser interromper seu serviço principal, execute: