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 的工作原理有許多誤解。首先不要利用衝突來排除目標。應避免同時運作衝突的服務。

如果一個單元在另一個單元上有 Conflicts= 設置,則啟動前者將停止後者,反之亦然。

單位是指啟動特定服務的 .service 文件,而不是要達到的目標。換句話說,Conflicts=reboot.target充其量是毫無意義的,最糟的情況是它會阻止您重新啟動。不要這樣做。這並不意味著重新啟動時不要運行它。這意味著根據時間以及 systemd 如何解釋這種錯誤使用衝突來中止此服務或reboot.target。

以下是當前設定單元(又稱 .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 使用的備用關閉路徑,也無法透過重新啟動來存取。 install 部分告訴 systemd 將此服務新增至必須在先前完成poweroff.targethalt.target將被視為已達到的清單中。

該服務已安裝並在我的系統上運行。

答案4

我已經測試了這裡和各個網站上的大部分帖子。唯一真正只在重新啟動時運行(不再啟動時運行 - 但實際上在 shutdown-halt-poweroff 時失敗)的是 @benoit2600 的帖子。他的第二個/解決方案帖子

但經過測試,我發現您可以在單元中使用所有 4 個目標,並且僅在其中一個實際使用時運行。根據他和您的需求休息在“ExecStop = mycommand”中,我剛剛輸入了我的直接命令(因為我不需要完整的bash)

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

相關內容