systemd에서 OnFailure를 사용하는 올바른 방법

systemd에서 OnFailure를 사용하는 올바른 방법

존재하지 않는 경우 일부 구성 파일을 생성하고 존재하는 경우 읽는 소프트웨어를 실행하는 서비스가 있습니다. 제가 직면했던 문제는 이러한 파일이 때때로 손상되어 소프트웨어가 시작되지 않고 서비스가 실패하게 된다는 것입니다. 이 경우 해당 파일을 삭제하고 서비스를 다시 시작하고 싶습니다.

다음과 같이 실패 시 실행되어야 하는 서비스를 만들려고 합니다.

[Service]
ExecStart=/bin/run_program
OnFailure=software-fail.service

서비스는 어디에 있습니까?

[Service]
ExecStart=/bin/rm /file/to/delete
ExecStop=systemctl --user start software.service

그런데 문제는 서비스가 실패해도 시작되지 않는다는 점이다.
나는 ~하려고 노력한다

systemctl --user enable software-fail.service

하지만 다른 서비스와 마찬가지로 시스템이 부팅될 때마다 시작됩니다.

내 임시 해결책은

ExecStopPost=/bin/rm /file/to/delete

하지만 이는 결함으로 인한 것인지 아닌지에 관계없이 서비스가 중지되면 항상 파일을 삭제하기 때문에 만족스러운 해결책이 아닙니다.

실패 시 출력:

● software.service - Software
   Loaded: loaded (/home/trippelganger/.config/systemd/user/software.service; enabled;  vendor preset: enabled)
   Active: failed (Result: exit-code) since Fri 2018-05-04 09:05:26 CEST; 5s ago
  Process: 1839 ExecStart=/bin/run_program (code=exited, status=1/FAILURE)
 Main PID: 1839 (code=exited, status=1/FAILURE)



May 04 09:05:26 trippelganger systemd[595]: software.service: Main process exited, code=exited, status=1/FAILURE
May 04 09:05:26 trippelganger systemd[595]: software.service: Unit entered failed state.
May 04 09:05:26 trippelganger systemd[595]: software.service: Failed with result 'exit-code'.

systemctl --user status Software-fail.service의 출력은 다음과 같습니다.

● software-fail.service - Delete corrupt files
   Loaded: loaded (/home/trippelganger/.config/systemd/user/software-fail.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

답변1

노트ExecStopPost=: 여기에서 대신 사용하고 싶을 수도 있지만 OnFailure=(다른 답변 참조) OnFailure=설정이 작동하지 않는 이유를 해결하려고 시도합니다.

장치를 시작할 수 없는 문제는 장치 가 있어야 OnFailure=할 잘못된 부분에 있기 때문일 수 있습니다 .[Unit][Service]

다음을 시도해 볼 수 있습니다.

# software.service
[Unit]
Description=Software
OnFailure=software-fail.service

[Service]
ExecStart=/bin/run_program

그리고:

# software-fail.service
[Unit]
Description=Delete corrupt files

[Service]
ExecStart=/bin/rm /file/to/delete
ExecStop=/bin/systemctl --user start software.service

이 설정으로 작동하게 만들 수 있습니다.

그러나 OnFailure=프로그램이 실패한 이유를 실제로 알 수 없고 ExecStop=직접 호출하여 다른 시작을 연결하는 것은 다소 구식이므로 여기서 사용하는 것은 이상적이지 않습니다. 종료의 /bin/systemctl start해결 방법을 사용하고 확인하십시오. 상태 프로그램이 절대적으로 우수합니다.ExecStopPost=

OnFailure=inside 를 정의하면 [Service]systemd(최소 Fedora 27 버전 234)는 다음과 같은 오류를 표시합니다.

software.service:6: Unknown lvalue 'OnFailure' in section 'Service'

로그에 이 내용이 표시되는지 확실하지 않습니다... (최근 systemd에 추가되었을 수도 있습니다.) 이는 거기에서 무슨 일이 일어나고 있는지 힌트를 줄 것입니다.

답변2

서비스가 실패할 때 일부 정리를 수행하려면 다음을 사용할 수 있습니다.ExecStopPost=, 서비스 성공 여부에 관계없이 실행됩니다.

실행 중인 코드에서 또는 중 하나를 사용하여 ExecStopPost=실패 조건을 확인하고 적절한 조치를 취할 수 있습니다. 보다$SERVICE_RESULT$EXIT_CODE$EXIT_STATUS문서어떤 환경 변수가 귀하에게 적합한지 확인하려면 다음 환경 변수를 확인하세요.

Restart=on-failure그런 다음 실패할 경우 systemd를 사용하여 장치를 다시 시작할 수 있습니다 .

모두 합치면 이런 모습이 됩니다. 파일이 손상될 때마다 상태 2로 종료한다고 가정하면 run_program(위 문서의 다른 오류 시나리오에 이를 적용할 수 있기를 바랍니다) 다음과 같이 작동합니다.

[Service]
ExecStart=/bin/run_program
ExecStopPost=/bin/sh -c 'if [ "$$EXIT_STATUS" = 2 ]; then rm /file/to/delete; fi'
Restart=on-failure

(노트: 쉘이 변수를 $$보고 액세스할 수 있도록 이중 달러 기호가 systemd로 이스케이프됩니다. $EXIT_STATUS단일 달러 기호를 사용하는 것도 작동하지만 systemd는 대체를 수행하고 쉘은 [ "2" = 2 ]말하자면 작동하는 것을 볼 것입니다... 어쨌든 이 모든 논리를 쉘 스크립트에 넣고 Most를 호출하여 문제를 해결할 수 있습니다. 그 중 전체 경로를 통과하는 ExecStopPost=것이 더 나을 수 있으며 오류 상황에서 복구하기 위해 수행된 작업을 기록하는 등 스크립트에 더 많은 명령을 쉽게 추가할 수 있습니다. )

이것이 귀하의 특정 상황에 맞게 올바르게 구성하는 방법에 대한 충분한 지침이 되기를 바랍니다.

답변3

주의해야 할 것은 systemd버전입니다. $EXIT_STATUS2017년 5월에 출시된 Systemd 버전 232에는 이점 및 관련 가치가 도입되었습니다.

RHEL 7.x와 같은 일부 배포판(입력 당시)은 여전히 ​​systemd 버전 219를 사용하고 있는데, 이는 $EXIT_STATUS.

관련 정보