저는 임베디드 시스템에서 systemd 231을 사용하고 있으며 시스템의 하드웨어 구성 요소를 모니터링하는 서비스를 만들려고 합니다. 내가하고 싶은 일에 대한 대략적인 설명은 다음과 같습니다.
- 서비스가
foo.service
시작되면 애플리케이션이 시작됩니다foo_app
. foo_app
지속적으로 실행되는 하드웨어 구성 요소를 모니터링합니다.- 하드웨어 오류가 감지 되면
foo_app
코드 1로 종료됩니다. 그러면 시스템이 다시 시작됩니다. - 충돌이 발생 하면
foo_app
systemd를 다시 시작해야 합니다foo_app
. - 만약에
foo_app
자꾸충돌이 발생하면 systemd는 시스템을 다시 시작해야 합니다.
다음은 이를 서비스로 구현하려는 시도입니다.
[Unit]
Description=Foo Hardware Monitor
# If the application fails 3 times in 30 seconds, something has gone wrong,
# and the state of the hardware can't be guaranteed. Reboot the system here.
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=reboot
# StartLimitAction=reboot will reboot the box if the app fails repeatedly,
# but if the app exits voluntarily, the reboot should trigger immediately
OnFailure=systemd-reboot.service
[Service]
ExecStart=/usr/bin/foo_app
# If the app fails from an abnormal condition (e.g. crash), try to
# restart it (within the limits of StartLimit*).
Restart=on-abnormal
문서에서 (시스템 서비스그리고시스템 서비스foo_app
), 트리거 방식으로 종료하는 경우 Restart=on-abnormal
(예 killall -9 foo_app
: ) systemd가 start 대신 우선 Restart=on-abnormal
순위 를 지정해야 합니다 .OnFailure=systemd-reboot.service
systemd-reboot.service
그러나 내가 본 것은 그렇지 않았습니다. 한 번 죽이면 foo_app
시스템이 즉시 재부팅됩니다.
다음은 문서의 관련 조각입니다.
OnFailure=
이 장치가 "실패" 상태에 들어갈 때 활성화되는 하나 이상의 장치를 공백으로 구분한 목록입니다. Restart=를 사용하는 서비스 장치는 시작 제한에 도달한 후에만 오류 상태로 들어갑니다.
Restart=
[자르다]서비스 다시 시작에는 StartLimitIntervalSec= 및 StartLimitBurst=로 구성된 장치 시작 속도 제한이 적용됩니다. 자세한 내용은 systemd.unit(5)을 참조하세요. 다시 시작된 서비스는 시작 제한에 도달한 후에만 실패 상태가 됩니다.
문서는 명확해 보입니다.
- 에 지정된 서비스는 서비스가 " " 상태로 전환될 때만 실행
OnFailure
되어야 합니다.failed
- 서비스는 만족된 후에만 " " 상태로 들어가야 합니다
failed
.StartLimitIntervalSec
StartLimitBurst
내가 본 것은 그게 아니다.
이를 확인하기 위해 서비스 파일을 다음과 같이 편집했습니다.
[Unit]
Description=Foo Hardware Monitor
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=none
[Service]
ExecStart=/usr/bin/foo_app
Restart=on-abnormal
을 제거 OnFailure
하고 설정 함으로써 StartLimitAction=none
systemd가 죽음에 어떻게 반응하는지 확인할 수 있었습니다 foo_app
. 이것은 foo_app
내가 죽이기 위해 반복적으로 사용한 테스트 이다 SIGKILL
.
[root@device ~]
# systemctl start foo.service
[root@device ~]
# journalctl -f -o cat -u foo.service &
[1] 2107
Started Foo Hardware Monitor.
[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
Started foo.
[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
Started foo.
[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
foo.service: Start request repeated too quickly
Failed to start foo.
foo.service: Unit entered failed state.
foo.service: Failed with result 'start-limit-hit'
이것은 의미가 있거나 대부분입니다. foo_app
종료 되면 systemd는 StartLimitBurst
적중할 때까지 다시 시작한 다음 포기합니다. 을 제외하고는 이것이 내가 원하는 것입니다 StartLimitAction=reboot
.
비정상적으로 systemd는 재부팅을 통과하려고 하는 경우에도 종료될 foo.service: Unit entered failed state.
때마다 foo_app
인쇄합니다 Restart=on-abnormal
. 이는 위에 인용된 문서의 다음 내용과 직접적으로 모순되는 것 같습니다.
Restart=를 사용하는 서비스 장치는 시작 제한에 도달한 후에만 오류 상태에 들어갑니다.
다시 시작된 서비스는 시작 제한에 도달한 후에만 실패 상태가 됩니다.
이 모든 것이 나를 혼란스럽게 합니다. 이러한 systemd 옵션을 오해 했습니까? 시스템 오류인가요? 도움을 주시면 감사하겠습니다.
답변1
2019/08/12 편집자:therealjumbo
의견 에 따르면 이 문제에 대한 수정 사항은 systemd
v239와 병합되어 릴리스되었으므로 릴리스로 인해 특정 버전에 고정되지 않은 경우(CentOS를 바라보며)업데이트하고 행복하세요!
TL;DR - 알려진 문서 문제, 현재 systemd
프로젝트에 대한 미해결 문제
문의하신 이후에 이런 내용이 보도된 것으로 확인되었습니다.차이로 인식systemd
문서화와 실제 동작 사이 어딘가에 있습니다 . 내 이해(및 github 문제에 대한 내 읽기)에 따르면 귀하의 기대는 문서와 일치하므로 미친 것은 아닙니다.
현재는 systemd
실행 제한에 도달했는지 여부에 관계없이 각 부팅 시도 후에 상태가 실패로 설정됩니다. 이번 호에서 OP는 자전거 타는 법을 배우는 것에 관한 흥미로운 일화를 썼는데, 꼭 확인해 보시길 강력히 추천합니다.