ExecStop 실패 시 Systemd 상태가 활성 상태로 유지됩니다.

ExecStop 실패 시 Systemd 상태가 활성 상태로 유지됩니다.

스크립트에 오류가 발생하면 ExecStop=/usr/lib/pick/d3shutdown_custom pick0systemd가 종료 프로세스를 중단하고 상태로 돌아가기를 원합니다 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 statusstderr에 오류 메시지를 남기는 것을 방지할 수 있습니다. 이렇게 하려면 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

관련 정보