스크립트에 오류가 발생하면 ExecStop=/usr/lib/pick/d3shutdown_custom pick0
systemd가 종료 프로세스를 중단하고 상태로 돌아가기를 원합니다 active
.
스크립트가 코드 4(사용자 권한 부족)로 종료되면 systemd가 해당 상태에 갇히게 됩니다 deactivating
.
이것은 내 시스템 서비스 파일입니다
[Unit]
Description=D3 multivalue database
After=d3_sn.service rslm.service
Requires=rslm.service
Wants=d3_sn.service
[Service]
Type=forking
ExecStart=/usr/bin/d3 -n pick0 -s -a x
ExecStop=/usr/lib/pick/d3shutdown_custom pick0
TimeoutSec=0
RemainAfterExit=true
SuccessExitStatus=11
[Install]
WantedBy=multi-user.target
d3shutdown_custom
이것은 스크립트의 일부입니다
log_error() {
echo -e "Error: $1"
echo "Aborting program ... "
echo " "
}
if [ ! -f "$D3_PROPERTIES_FILE" ]; then log_error "File $D3_PROPERTIES_FILE not found."; exit 2; fi
source $D3_PROPERTIES_FILE
export PICKUSER
export PICKUPASS
if d3 -q | grep -q 'not running'; then
exit 11
fi
D3TCL=$(/usr/bin/d3tcl 'listu')
if echo $D3TCL | grep -q 'Bad User or User Password'; then log_error "Bad password"; exit 4; fi
답변1
좀 까다로운 요청이네요. 당신이 뭔가를 할 때 systemctl stop
, 그것은~해야 한다그리고~ 할 것이다항상 내려가세요. 실패할 수도 있지만, systemd
꼭 그래야 한다고 해도 결국에는 멈출 것입니다.FinalKillSignal=(SIGKILL)
~ 후에TimeStopSec=(90s)
.
조건이 실패하면 "종료" 또는 "다시 시작"과 같은 작업은 불가능하며 이러한 작업은 항상 가능해야 합니다.
나는 이것을 달성하는 가장 좋은 방법은 다음과 같다고 생각합니다.Conflicts=
조건부로 충돌하는 장치를 시작하는 장치 및 장치OnFailure=
. 이것은 당신이 systemctl stop my-unit
생각을 바꿔야 함을 의미합니다 systemctl start maybe-kill-my-unit
.
이것이 종료가 작동하는 방식입니다. 우리는 다른 유닛, 우리를 막지 않을 것입니다 systemctl start shutdown.target
.
c.service
사람들이 직접 사용하는 것을 방지하여 systemctl stop a.service
사용을 더욱 강화할 수 있습니다.RefuseManualStop=yes
.
a.service
[Unit]
Description=Long running service
RefuseManualStop=yes
[Service]
ExecStart=/bin/sleep 60
b.service
[Unit]
Description=Killer of the long running service
Conflicts=a
[Service]
Type=oneshot
ExecStart=/bin/true
c.service
[Unit]
Description=Conditional killer of the long runing service
OnFailure=b
[Service]
Type=oneshot
ExecStart=/usr/local/bin/myscript
다음은 실제적인 예입니다( c
실패한 경우).
$ systemctl --user start a
$ systemctl --user start c
Job for c.service failed because the control process exited with error code.
$ systemctl --user status a b c --lines 0
● a.service
Loaded: loaded (.config/systemd/user/a.service; static)
Active: inactive (dead) since Mon 2023-10-09 16:10:18 CEST; 3s ago
● b.service
Loaded: loaded (.config/systemd/user/b.service; static)
Active: inactive (dead) since Mon 2023-10-09 16:10:18 CEST; 3s ago
● c.service
Loaded: loaded (.config/systemd/user/c.service; static)
Active: failed (Result: exit-code) since Mon 2023-10-09 16:10:18 CEST; 3s ago
$ journalctl --user -u a -u b -u c --since "1 minute ago"
Oct 09 16:10:14: Long running service
Oct 09 16:10:18: Starting Conditional killer of the long runing service
Oct 09 16:10:18: c.service: Main process exited, code=exited, status=1/FAILURE
Oct 09 16:10:18: c.service: Triggering OnFailure= dependencies.
Oct 09 16:10:18: Starting Killer of the long running service...
Oct 09 16:10:18: Stopping Long running service...
Oct 09 16:10:18: Finished Killer of the long running service.
성공적인 예 는 다음과 같습니다 c
.
$ systemctl --user start a
$ systemctl --user start c
$ systemctl --user status a b c --lines 0
● a.service
Loaded: loaded (.config/systemd/user/a.service; static)
Active: active (running) since Mon 2023-10-09 16:14:45 CEST; 9s ago
● b.service
Loaded: loaded (.config/systemd/user/b.service; static)
Active: inactive (dead)
● c.service
Loaded: loaded (.config/systemd/user/c.service; static)
Active: inactive (dead)
$ journalctl --user -u a -u b -u c --since "1 minute ago"
Oct 09 16:14:45: Started Long running service.
Oct 09 16:14:50: Starting Conditional killer of the long runing service...
Oct 09 16:14:50: Finished Conditional killer of the long runing service.
a
이것이 실패 하면 c
예제가 중지됩니다. 스크립트가 반전된 경우( c
성공하면 중지되어야 함) 재생할 수 있습니다.SuccessExitStatus=
.
최신 버전의 systemd가 있는 경우 다음 명령을 사용하여 더욱 우아하게 만들 수 있습니다.ExecCondition=
결합하다OnSuccess=
. 이렇게 하면 장치가 실패한 상태로 남아 전역 "다운그레이드"를 오염시키고 systemctl status
stderr에 오류 메시지를 남기는 것을 방지할 수 있습니다. 이렇게 하려면 ExecCondition=
스크립트를 실행하세요. 성공하면 ExecStart=
성공 하고 OnSuccess=
행동을 촉발하며 b.service
사람을 죽입니다 a.service
. ExecCondition=
실패 하면 ExecStart=
실행되거나 OnSuccess=
트리거되지 않으므로 생존이 가능합니다 a.service
.
c.service
[Unit]
OnSuccess=b.service
[Service]
Type=oneshot
ExecCondition=/your-script
ExecStart=/bin/true