종속성 중 하나가 시작 시 실패하지만 재시도 후에 성공하는 경우 서비스 다시 시작을 처리하는 올바른 방법은 무엇입니까?
이는 문제를 더 명확하게 하기 위해 고안된 재현입니다.
서비스(시뮬레이션은 첫 번째 시도에서 실패하고 두 번째 시도에서 성공합니다.)
[Unit]
Description=A
[Service]
ExecStartPre=/bin/sh -x -c "[ -f /tmp/success ] || (touch /tmp/success && sleep 10)"
ExecStart=/bin/true
TimeoutStartSec=5
Restart=on-failure
RestartSec=5
RemainAfterExit=yes
b.서비스(A가 시작된 후 성공)
[Unit]
Description=B
After=a.service
Requires=a.service
[Service]
ExecStart=/bin/true
RemainAfterExit=yes
Restart=on-failure
RestartSec=5
b부터 시작해보자:
# systemctl start b
A dependency job for b.service failed. See 'journalctl -xe' for details.
통나무:
Jun 30 21:34:54 debug systemd[1]: Starting A...
Jun 30 21:34:54 debug sh[1308]: + '[' -f /tmp/success ']'
Jun 30 21:34:54 debug sh[1308]: + touch /tmp/success
Jun 30 21:34:54 debug sh[1308]: + sleep 10
Jun 30 21:34:59 debug systemd[1]: a.service start-pre operation timed out. Terminating.
Jun 30 21:34:59 debug systemd[1]: Failed to start A.
Jun 30 21:34:59 debug systemd[1]: Dependency failed for B.
Jun 30 21:34:59 debug systemd[1]: Job b.service/start failed with result 'dependency'.
Jun 30 21:34:59 debug systemd[1]: Unit a.service entered failed state.
Jun 30 21:34:59 debug systemd[1]: a.service failed.
Jun 30 21:35:04 debug systemd[1]: a.service holdoff time over, scheduling restart.
Jun 30 21:35:04 debug systemd[1]: Starting A...
Jun 30 21:35:04 debug systemd[1]: Started A.
Jun 30 21:35:04 debug sh[1314]: + '[' -f /tmp/success ']'
A는 성공적으로 시작되지만 B는 실패 상태이므로 재시도하지 않습니다.
편집하다
두 서비스 모두에 다음을 추가했으며 이제 A가 시작되면 B가 성공적으로 시작되지만 이유를 설명할 수 없습니다.
[Install]
WantedBy=multi-user.target
이것이 A와 B의 관계에 영향을 미치는 이유는 무엇입니까?
편집 2
위의 "수정"은 systemd 220에서는 작동하지 않습니다.
systemd 219 디버그 로그
systemd219 systemd[1]: Trying to enqueue job b.service/start/replace
systemd219 systemd[1]: Installed new job b.service/start as 3454
systemd219 systemd[1]: Installed new job a.service/start as 3455
systemd219 systemd[1]: Enqueued job b.service/start as 3454
systemd219 systemd[1]: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch oldcoreos
systemd219 systemd[1]: Forked /bin/sh as 1502
systemd219 systemd[1]: a.service changed dead -> start-pre
systemd219 systemd[1]: Starting A...
systemd219 systemd[1502]: Executing: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmpoldcoreos
systemd219 sh[1502]: + '[' -f /tmp/success ']'
systemd219 sh[1502]: + touch /tmp/success
systemd219 sh[1502]: + sleep 10
systemd219 systemd[1]: a.service start-pre operation timed out. Terminating.
systemd219 systemd[1]: a.service changed start-pre -> final-sigterm
systemd219 systemd[1]: Child 1502 belongs to a.service
systemd219 systemd[1]: a.service: control process exited, code=killed status=15
systemd219 systemd[1]: a.service got final SIGCHLD for state final-sigterm
systemd219 systemd[1]: a.service changed final-sigterm -> failed
systemd219 systemd[1]: Job a.service/start finished, result=failed
systemd219 systemd[1]: Failed to start A.
systemd219 systemd[1]: Job b.service/start finished, result=dependency
systemd219 systemd[1]: Dependency failed for B.
systemd219 systemd[1]: Job b.service/start failed with result 'dependency'.
systemd219 systemd[1]: Unit a.service entered failed state.
systemd219 systemd[1]: a.service failed.
systemd219 systemd[1]: a.service changed failed -> auto-restart
systemd219 systemd[1]: a.service: cgroup is empty
systemd219 systemd[1]: a.service: cgroup is empty
systemd219 systemd[1]: a.service holdoff time over, scheduling restart.
systemd219 systemd[1]: Trying to enqueue job a.service/restart/fail
systemd219 systemd[1]: Installed new job a.service/restart as 3718
systemd219 systemd[1]: Installed new job b.service/restart as 3803
systemd219 systemd[1]: Enqueued job a.service/restart as 3718
systemd219 systemd[1]: a.service scheduled restart job.
systemd219 systemd[1]: Job b.service/restart finished, result=done
systemd219 systemd[1]: Converting job b.service/restart -> b.service/start
systemd219 systemd[1]: a.service changed auto-restart -> dead
systemd219 systemd[1]: Job a.service/restart finished, result=done
systemd219 systemd[1]: Converting job a.service/restart -> a.service/start
systemd219 systemd[1]: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch oldcoreos
systemd219 systemd[1]: Forked /bin/sh as 1558
systemd219 systemd[1]: a.service changed dead -> start-pre
systemd219 systemd[1]: Starting A...
systemd219 systemd[1]: Child 1558 belongs to a.service
systemd219 systemd[1]: a.service: control process exited, code=exited status=0
systemd219 systemd[1]: a.service got final SIGCHLD for state start-pre
systemd219 systemd[1]: About to execute: /bin/true
systemd219 systemd[1]: Forked /bin/true as 1561
systemd219 systemd[1]: a.service changed start-pre -> running
systemd219 systemd[1]: Job a.service/start finished, result=done
systemd219 systemd[1]: Started A.
systemd219 systemd[1]: Child 1561 belongs to a.service
systemd219 systemd[1]: a.service: main process exited, code=exited, status=0/SUCCESS
systemd219 systemd[1]: a.service changed running -> exited
systemd219 systemd[1]: a.service: cgroup is empty
systemd219 systemd[1]: About to execute: /bin/true
systemd219 systemd[1]: Forked /bin/true as 1563
systemd219 systemd[1]: b.service changed dead -> running
systemd219 systemd[1]: Job b.service/start finished, result=done
systemd219 systemd[1]: Started B.
systemd219 systemd[1]: Starting B...
systemd219 systemd[1]: Child 1563 belongs to b.service
systemd219 systemd[1]: b.service: main process exited, code=exited, status=0/SUCCESS
systemd219 systemd[1]: b.service changed running -> exited
systemd219 systemd[1]: b.service: cgroup is empty
systemd219 sh[1558]: + '[' -f /tmp/success ']'
systemd 220 디버그 로그
systemd220 systemd[1]: b.service: Trying to enqueue job b.service/start/replace
systemd220 systemd[1]: a.service: Installed new job a.service/start as 4846
systemd220 systemd[1]: b.service: Installed new job b.service/start as 4761
systemd220 systemd[1]: b.service: Enqueued job b.service/start as 4761
systemd220 systemd[1]: a.service: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmp/success && sleep 10)'
systemd220 systemd[1]: a.service: Forked /bin/sh as 2032
systemd220 systemd[1]: a.service: Changed dead -> start-pre
systemd220 systemd[1]: Starting A...
systemd220 systemd[2032]: a.service: Executing: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmp/success && sleep 10)'
systemd220 sh[2032]: + '[' -f /tmp/success ']'
systemd220 sh[2032]: + touch /tmp/success
systemd220 sh[2032]: + sleep 10
systemd220 systemd[1]: a.service: Start-pre operation timed out. Terminating.
systemd220 systemd[1]: a.service: Changed start-pre -> final-sigterm
systemd220 systemd[1]: a.service: Child 2032 belongs to a.service
systemd220 systemd[1]: a.service: Control process exited, code=killed status=15
systemd220 systemd[1]: a.service: Got final SIGCHLD for state final-sigterm.
systemd220 systemd[1]: a.service: Changed final-sigterm -> failed
systemd220 systemd[1]: a.service: Job a.service/start finished, result=failed
systemd220 systemd[1]: Failed to start A.
systemd220 systemd[1]: b.service: Job b.service/start finished, result=dependency
systemd220 systemd[1]: Dependency failed for B.
systemd220 systemd[1]: b.service: Job b.service/start failed with result 'dependency'.
systemd220 systemd[1]: a.service: Unit entered failed state.
systemd220 systemd[1]: a.service: Failed with result 'timeout'.
systemd220 systemd[1]: a.service: Changed failed -> auto-restart
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: Failed to send unit change signal for a.service: Transport endpoint is not connected
systemd220 systemd[1]: a.service: Service hold-off time over, scheduling restart.
systemd220 systemd[1]: a.service: Trying to enqueue job a.service/restart/fail
systemd220 systemd[1]: a.service: Installed new job a.service/restart as 5190
systemd220 systemd[1]: a.service: Enqueued job a.service/restart as 5190
systemd220 systemd[1]: a.service: Scheduled restart job.
systemd220 systemd[1]: a.service: Changed auto-restart -> dead
systemd220 systemd[1]: a.service: Job a.service/restart finished, result=done
systemd220 systemd[1]: a.service: Converting job a.service/restart -> a.service/start
systemd220 systemd[1]: a.service: About to execute: /bin/sh -x -c '[ -f /tmp/success ] || (touch /tmp/success && sleep 10)'
systemd220 systemd[1]: a.service: Forked /bin/sh as 2132
systemd220 systemd[1]: a.service: Changed dead -> start-pre
systemd220 systemd[1]: Starting A...
systemd220 systemd[1]: a.service: Child 2132 belongs to a.service
systemd220 systemd[1]: a.service: Control process exited, code=exited status=0
systemd220 systemd[1]: a.service: Got final SIGCHLD for state start-pre.
systemd220 systemd[1]: a.service: About to execute: /bin/true
systemd220 systemd[1]: a.service: Forked /bin/true as 2136
systemd220 systemd[1]: a.service: Changed start-pre -> running
systemd220 systemd[1]: a.service: Job a.service/start finished, result=done
systemd220 systemd[1]: Started A.
systemd220 systemd[1]: a.service: Child 2136 belongs to a.service
systemd220 systemd[1]: a.service: Main process exited, code=exited, status=0/SUCCESS
systemd220 systemd[1]: a.service: Changed running -> exited
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 systemd[1]: a.service: cgroup is empty
systemd220 sh[2132]: + '[' -f /tmp/success ']'
답변1
이 주제에 대한 정보가 거의 없기 때문에 다른 사람이 이 문제에 직면할 경우를 대비하여 이 문제에 대한 제가 찾은 내용을 요약하려고 합니다.
Restart=on-failure
프로세스 실패에만 적용 (종속성 실패로 인한 실패에는 적용되지 않음)- 종속성이 성공적으로 다시 시작되면 특정 조건에서 실패한 종속성이 있는 장치가 다시 시작되었습니다. systemd <220의 버그: http://lists.freedesktop.org/archives/systemd-devel/2015-July/033513.html
- 시작 시 종속성이 실패할 가능성이 적고 복원력이 중요하다면
Before
/를 사용하지 말고After
대신 종속성에 의해 생성된 일부 아티팩트를 확인하세요.
예를 들어
ExecStartPre=/usr/bin/test -f /some/thing
Restart=on-failure
RestartSec=5s
를 사용할 수도 있습니다 systemctl is-active <dependecy>
.
매우 해키지만 아직 더 나은 옵션을 찾지 못했습니다.
제 생각에는 종속성 오류를 처리할 수 있는 방법이 없는 것은 systemd의 결함입니다.
답변2
이는 쉽게 스크립트를 작성하여 cronjob에 넣을 수 있는 것처럼 보입니다. 기본적인 논리는 이렇습니다
- 서비스 a와 b 및 종속성이 실행 중이거나 유효한 상태인지 확인하세요. 모든 것이 제대로 작동하는지 확인하는 가장 좋은 방법을 알게 될 것입니다.
- 모든 것이 정상이면 아무것도 하지 않거나 모든 것이 정상임을 기록하십시오. 로깅의 장점은 이전 로그 항목을 찾을 수 있다는 것입니다.
- 문제가 발생하면 서비스를 다시 시작하고 서비스 및 종속성 상태 확인을 수행하는 스크립트의 시작 부분으로 돌아갑니다. 점프는 서비스를 다시 시작하고 종속성이 작동할 가능성이 높다고 확신하는 경우에만 발생해야 합니다. 그렇지 않으면 루프가 발생할 수 있습니다.
- cron이 나중에 스크립트를 다시 실행하도록 하세요.
스크립트가 설정되면 cron은 이를 테스트하기에 좋은 장소이며, cron이 비효율적이라면 스크립트는 다른 서비스의 상태를 확인할 수 있는 낮은 수준의 시스템 서비스를 작성하기 위한 좋은 시작점이 될 것입니다. 필요에 따라 서비스를 다시 시작합니다. 얼마나 많은 노력을 기울이고 싶은지에 따라 결과에 따라 이메일을 보내도록 스크립트를 설정할 수도 있습니다(물론 해당 서비스가 웹 서비스인 경우는 제외).
답변3
After
그리고 Before
서비스가 시작되는 순서를 설정하면 서비스 파일에 "A와 B가 시작하려면 A가 B보다 먼저 시작해야 합니다"라고 표시됩니다.
Requires
이 서비스를 시작하려면 먼저 시작해야 함을 의미합니다. 예에서 "B가 시작되고 A가 실행되고 있지 않으면 A를 시작합니다"
이를 추가하면 WantedBy=multi-user.target
이제 시스템이 초기화될 때 서비스를 시작해야 한다고 시스템에 알리는 것입니다. multi-user.target
아마도 서비스를 추가하면 수동으로 시작하는 대신 시스템이 서비스를 시작하도록 허용한다는 의미일까요?
왜 이것이 버전 220에서 작동하지 않는지 잘 모르겠습니다. 222를 시도해 볼 가치가 있을 것입니다. 기회가 되면 가상 머신을 파헤쳐 서비스를 시도해 보겠습니다.
답변4
https://github.com/systemd/systemd/issues/1312#issuecomment-1139234399
관심이 없지만
Upholds=
커밋에 새로운 것이 도입됩니까?0bc488cPR #19322의 내용이 여기에 도움이 됩니까?특히
b.service
구성에Wants=a.service
및After=a.service
및 이 있다고 가정합니다Restart=on-failure
. 그런 다음a.service
시작 시 시간 초과가 발생하여b.service
실패하고 표시됩니다b.service/start failed with result 'dependency'
. 다음으로a.service
재부팅은 성공하지만b.service
시작되지 않습니다. 분명히 종속성 실패는 스키마에 의한 트리거로 간주되지 않기 때문입니다Restart=on-failure
.(이미 연결된 Stack Exchange에 보고된 내용이 바로 이것입니다.질문답변 의견 중 하나도 이 질문으로 다시 연결됩니다. )
이 오랜 문제가 발생한 후 이 지시문이 ? 로 지정되고 구성
Upholds=
되면 영향을 미치는지 궁금합니다. 이것이 마침내 출시되면 출시로 이어질까요 ?a.service
Upholds=b.service
b.service
a.service
systemd를 다음으로 업그레이드할 수 있는 경우v254
반품시험해 보세요 RestartMode=direct
:https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#RestartMode=