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-control-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의 작동 방식에 대해 많은 오해가 있는 것 같습니다. 우선 목표를 없애기 위해 갈등을 이용하지 마십시오. 충돌하는 서비스를 동시에 실행하는 것은 피해야 합니다.

한 유닛이 다른 유닛에 충돌=을 설정한 경우 전자를 시작하면 후자는 중지되고 그 반대의 경우도 마찬가지입니다.

단위는 달성할 목표가 아닌 특정 서비스를 시작하는 .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

관련 정보