존재하지 않는 경우 일부 구성 파일을 생성하고 존재하는 경우 읽는 소프트웨어를 실행하는 서비스가 있습니다. 제가 직면했던 문제는 이러한 파일이 때때로 손상되어 소프트웨어가 시작되지 않고 서비스가 실패하게 된다는 것입니다. 이 경우 해당 파일을 삭제하고 서비스를 다시 시작하고 싶습니다.
다음과 같이 실패 시 실행되어야 하는 서비스를 만들려고 합니다.
[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_STATUS
2017년 5월에 출시된 Systemd 버전 232에는 이점 및 관련 가치가 도입되었습니다.
RHEL 7.x와 같은 일부 배포판(입력 당시)은 여전히 systemd 버전 219를 사용하고 있는데, 이는 $EXIT_STATUS
.