Systemd : 종료 시에만(재부팅 시에는 아님) 스크립트를 실행하는 방법

Systemd : 종료 시에만(재부팅 시에는 아님) 스크립트를 실행하는 방법

여기에는 종료/재부팅 시 스크립트를 실행하는 많은 솔루션이 있지만 내 스크립트는 종료 시에만 실행되기를 원합니다.

내 스크립트를 /usr/lib/systemd/systemd-shutdown에 넣고 $1 매개변수를 확인하려고 했습니다.여기, 하지만 작동하지 않습니다.

어떤 아이디어가 있나요?

시스템 : gnome-shell을 사용하는 Archlinux

$systemctl --version                                                                                                                                                                                 
systemd 229
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN

답변1

마침내 그 방법을 찾았습니다.

약간 해킹적인 생각이지만 작동합니다.

나는 이 스레드의 일부를 사용했습니다.https://stackoverflow.com/questions/25166085/how-can-a-systemd-controled-service-distinguish-between-shutdown-and-reboot

그리고 이 스레드는: 종료 직전에 systemd로 스크립트를 실행하는 방법은 무엇입니까?

내가 이 서비스를 만들었습니다./etc/systemd/system/shutdown_screen.service

[Unit]
Description=runs only upon shutdown
Conflicts=reboot.target
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/bin/bash /usr/local/bin/shutdown_screen
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

종료/재부팅/중지/무엇이든 실행됩니다. (활성화하는 것을 잊지 마세요)

그리고 내 스크립트에는 /usr/local/bin/shutdown_screen 다음을 넣었습니다.

#!/bin/bash
# send a shutdown message only at shutdown (not at reboot)    
/usr/bin/systemctl list-jobs | egrep -q 'reboot.target.*start' || echo "shutdown" | nc 192.168.0.180 4243 -w 1

그러면 내 화면이 종료되는 내 Arduino에 종료 메시지가 전송됩니다.

답변2

systemd.special맨페이지 에 따르면 Before=poweroff.target.

전원 끄기.대상

A special target unit for shutting down and powering off the system.

Applications wanting to power off the system should start this unit.

runlevel0.target is an alias for this target unit, for compatibility with SysV.

또한 내 의견에서 언급했듯이 /etc/systemd/system/. 디렉토리 /usr/lib/systemd/system/는 시스템 제공 스크립트에 사용됩니다.

아마도 다음과 같을 것입니다.

[Unit]
Description=runs only upon shutdown
DefaultDependencies=no
Conflicts=reboot.target
Before=shutdown.target
Requires=poweroff.target

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/usr/local/bin/yourscript
RemainAfterExit=yes

답변3

여기의 답변을 읽으면 systemd의 작동 방식에 대해 많은 오해가 있는 것 같습니다. 먼저 대상을 제외하기 위해 충돌을 사용하지 마십시오. 충돌하는 서비스가 동시에 실행되는 것을 방지하기 위한 것입니다.

한 장치에 다른 장치에 Confluence= 설정이 있는 경우 전자를 시작하면 후자도 중지되고 그 반대의 경우도 마찬가지입니다.

단위는 도달할 대상이 아닌 특정 서비스를 시작하기 위한 .service 파일을 의미합니다. 즉, 기껏해야 Conflicts=reboot.target의미가 없으며 최악의 경우 재부팅을 방지할 수 있습니다. 이러지 마세요. 재부팅할 때 이것을 실행하지 말라는 의미는 아닙니다. 이는 타이밍과 systemd가 이러한 잘못된 충돌 사용을 해석하는 방법에 따라 이 서비스 또는 재부팅.대상을 중단하는 것을 의미합니다.

다음은 재부팅이 아닌 종료 시에만 실행되는 현재 설정된 단위(즉, .service 파일)의 예입니다.

[Unit]
Description=Play sound
DefaultDependencies=no
Before=poweroff.target halt.target

[Service]
ExecStart=/usr/local/bin/playsound.sh
ExecStop=/usr/local/bin/playsound.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=poweroff.target halt.target 

poweroff.target은 종료 시에만 도달하는 이전 systemv 실행 레벨0과 동일합니다. Halt.target은 systemd에서 사용하는 대체 종료 경로이며 재부팅해도 도달할 수 없습니다. 설치 섹션에서는 systemd에게 이 서비스를 완료하기 전에 완료해야 poweroff.target하거나 halt.target도달한 것으로 간주되는 목록에 추가하도록 지시합니다 .

이 서비스는 내 시스템에 설치되어 실행 중입니다.

답변4

나는 여기에 있는 대부분의 게시물과 다양한 사이트를 테스트했습니다. 실제로 재부팅 시에만 실행되도록 작동한 유일한 항목(다시 부팅할 때는 아니지만 실제로 shutdown-halt-poweroff 시 실패함)은 @benoit2600의 게시물입니다. 그의 두 번째/솔루션 게시물

그러나 테스트 후에는 4개의 타겟을 모두 유닛에서 사용할 수 있으며 그 중 하나가 실제로 사용될 때만 실행된다는 사실을 발견했습니다. 그 사람과 당신의 필요에 따라 휴식하십시오. "ExecStop=mycommand"에 방금 직접 명령을 입력했습니다(전체 bash가 필요하지 않았기 때문에).

[Unit]
Conflicts=reboot.target poweroff.target halt.target shutdown.target

관련 정보