Service OnFailure는 버스트 제한에 도달한 후에만 트리거됩니다.

Service OnFailure는 버스트 제한에 도달한 후에만 트리거됩니다.

저는 systemd 단위 파일을 사용하여 서버에서 실행되는 Python 프로세스를 제어합니다(systemd v247 사용).

이 프로세스는 600초 내에 5번 실패하지 않는 한 실패 여부에 관계없이 종료 후 60초 후에 다시 시작해야 합니다.

이 유닛 파일은 이메일을 통한 장애 알림을 위해 다른 서비스에 연결됩니다.

/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

OnFailure기본 테스트 중에 트리거가 매우 잘 작동했습니다. 하지만 유닛 파일에 다음 섹션을 추가하면 OnFailure5번 연속 실패가 발생할 때만 실행됩니다.

StartLimitInterval=600
StartLimitBurst=5

아직 버스트 제한에 도달하지 않았더라도 프로세스가 실패할 때마다 알림을 받고 싶기 때문에 이는 내가 원하는 동작이 아닙니다.


프로세스 상태를 확인할 때 버스트 제한에 도달하지 않은 경우 출력이 다릅니다.

● 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'.

그때보다

● 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.

OnFailure유닛 파일 내에서 트리거를 수정하는 방법을 설명하는 내용을 찾을 수 없습니다 .

프로세스가 실패할 때마다 이메일로 알리면서도 버스트 제한을 유지하는 방법이 있습니까?

답변1

시스템 서비스를 필요에 맞게 이용하기 위해서는 몇 가지 작업을 수행해야 합니다. (변경 진행 중)/etc/systemd/system/python-test.service).

  1. Restart=always로 변경Restart=on-failure
  2. 이 값 도 지원되는 StartLimitInterval=600것으로 보입니다 . StartLimitBurst=5하지만 에 넣어야 합니다 . 를 [Unit]넣으면 이름을 바꿀 수 있습니다 ( 대신 사용 ).StartLimitInterval[Unit]StartLimitIntervalSecman systemd.unitStartLimitIntervalSec
  3. RemainAfterExit=no섹션 에 추가하세요 [Service].
  4. 섹션에 다음 줄을 추가하세요 [Service].TimeoutStopSec=infinity
  5. 스크립트의 환경 변수를 사용하여 EXIT_STATUS스크립트가 성공적으로 종료되었는지 확인합니다.
  6. 로 변경 . OnFailure=mailer@%n.serviceOnFailure=mailer@%N.service 의 차이점은 이를 사용하면 %N접미사가 삭제된다는 점입니다.
  7. 명령을 사용할 수 있도록 서비스 atd( )를 설치하고 시작합니다. 또는 사용하지 않으려면 다른 시스템 서비스를 작성하여 서비스를 다시 시작할 수 있습니다. (이 예에서는 를 사용했습니다 )sudo systemctl start atd.serviceatatrelaunch.service
  8. sleep및 에 동일한 값을 사용하십시오 RestartSec. 귀하의 경우에는 이 줄 RestartSec에서 수면 도 다음을 포함해야 합니다.6060
 echo "sleep 60; sudo systemctl start ${1}.service" | at now
  1. 사용 ExecStart하고 ExecStopPost=획득종료 상태주요 프로세스: /home/debian/tmp.py. ExecStop다음에서 을(를) 사용하지 마십시오 man systemd.service:

실행이 중지됨 =

ExecStop=에 지정된 명령은 서비스가 처음으로 성공적으로 시작될 때만 실행됩니다. 서비스가 전혀 시작된 적이 없거나 시작에 실패한 경우(예: ExecStart=, ExecStartPre= 또는 ExecStartPost=에 지정된 명령이 실패했기 때문에) 호출되지 않습니다("-" 접두사가 붙지 않았습니다. 위 참조). ) 또는 시간이 초과되었습니다. 서비스가 올바르게 시작되지 않고 다시 종료되면 ExecStopPost=와 함께 명령이 호출됩니다.


제공하다/etc/systemd/system/python-test.service해야 한다:

[Unit]
After=network.target
OnFailure=mailer@%N.service

StartLimitBurst=5
StartLimitIntervalSec=600
 
[Service]  
Type=simple 
TimeoutStopSec=infinity
ExecStart=/home/debian/tmp.py
ExecStopPost=/bin/bash -c 'echo The Service  has exited with values: $$EXIT_STATUS,$$SERVICE_RESULT,$$EXIT_CODE'
ExecStopPost=/home/debian/bin/checkSuccess "%N"
# Any exit status different than 0 is considered as an error
SuccessExitStatus=0
StandardOutput=append:/tmp/python-out-test.log
StandardError=append:/tmp/python-err-test.log
# Always restart service 60sec after exit
Restart=on-failure
RestartSec=60
RemainAfterExit=no

[Install]
WantedBy=multi-user.target

그리고/홈/데비안/bin/checkSuccess다음이 있어야 합니다.

해결 방법 1:사용 at명령:

#!/bin/bash

if [ "$EXIT_STATUS" -eq 0 ]
then
   echo "sleep 60; sudo systemctl start ${1}.service" | at now
   exit 0
else
   systemctl start "mailer@${1}.service"
   exit 0
fi

해결 방법 2:다른 시스템 서비스를 사용하십시오.

#!/bin/bash

if [ "$EXIT_STATUS" -eq 0 ]
then
   systemctl start relaunch.service
else
   systemctl start "mailer@${1}.service"
fi
exit 0

그리고 relaunch.service다음이 있어야 합니다:

[Unit]
Description=Relaunch Python Test Service

[Service]
Type=simple
RemainAfterExit=no 
ExecStart=/bin/bash -c 'echo Delay; sleep 10 ; systemctl start python-test.service'

"$EXIT_STATUS"systemd 서비스에 의해 설정된 변수는 종료 상태에 따라 결정됩니다 /home/debian/tmp.py.

${1}단위를 나타내는 이름: python-test라인의 스크립트에 전달합니다 /home/debian/bin/checkSuccess "%N".


노트:

  1. 'echo The Service %n has exited with values: $$EXIT_STATUS,$$SERVICE_RESULT,$$EXIT_CODE' 다음 명령어를 사용하면 실시간으로 로그를 확인할 수 있습니다.
tail -f /tmp/python-out-test.log
  1. relaunch.service기본 서비스를 중지하려면 솔루션 2( with )를 사용하는 경우 다음을 실행해야 합니다.
sudo systemctl stop relaunch.service
#Might not be necessary but you stop python service too:
# sudo systemctl stop python-test.service

관련 정보