如何在網路關閉之前觸發 systemd 單元掛起?
(庫存 Debian 測試又名拉伸 aka 9,所以我有一個正常的 systemd+logind+NetworkManager+GNOME 堆棧)
我有一對要在啟動/關閉和恢復/掛起時執行的腳本。此腳本在執行時需要存在網路。我已經嘗試使用以下腳本:
[Unit] Description=Yamaha Reciever power Requires=network-online.target After=network-online.target Before=sleep.target Conflicts=sleep.target [Service] Type=oneshot ExecStart=/usr/local/bin/av-up ExecStop=/usr/local/bin/av-down RemainAfterExit=yes [Install] WantedBy=graphical.target
這在啟動/關閉時可以正常工作,但是在掛起期間它會在網路關閉後執行,因此會失敗。
我已經確定這是因為在 systemd 下掛起是如何進行的:
- 掛起是由一個程序(例如
systemctl suspend
)向 logind 發送一個 dbus 呼叫啟動的。- Logind 然後向任何收聽的人發送 PrepareToShutdown dbus 信號。
- 然後 Logind 向 systemd 發送 StartUnit dbus 呼叫以執行 suspend.target 單元。
NetworkManager 監聽 PrepareToShutdown,因此在 (2) 處刪除網路,而我的單元在 systemd 實際上開始在 (3) 處暫停時被觸發。NetworkManager 使用 logind 保持“禁止”鎖定,以確保它在 (3) 之前關閉網路。(旁注:有類似 systemd control ordering of suspend/resume 之類的東西似乎很瘋狂,只是為了用 logind 來破壞它,讓東西繞過這個)
在網路仍在執行時觸發程序在掛起/恢復時執行的正確方法是什麼?
我應該使用 NetworkManager pre-down 腳本嗎?如果是這樣,如果網路出現故障但我沒有暫停,我該如何阻止它觸發?
有沒有辦法更早地掛鉤掛起過程?
有沒有辦法讓 NetworkManager 讓網路保持更長時間?
注意:這與如何編寫一個系統單元不同,該單元將在網路中斷之前觸發,因為我正在談論暫停/恢復。
受https://unix.stackexchange.com/a/139664/160746的啟發,我將啟動/停止腳本升級為完整的守護程序,並讓它監聽 PrepareToShutdown 信號。這是每次啟動/停止時與 NetworkManager 的競賽,但它似乎在我的系統上可靠地工作。
我已經在https://github.com/davidn/av上傳了我的程式碼和 systemd 單元。
根據systemd-suspend文件,以及systemctl 手冊頁
systemctl suspend
啟動suspend.target
.
systemctl list-dependencies suspend.target --after --all
顯示suspend.target
呼叫systemctl-suspend.service
thensleep.target
。這意味著當您呼叫預設操作順序時systemctl suspend
:suspend.target |-systemd-suspend.service |-sleep.target
如果您放置了
Before=sleep.target
,那麼您的操作順序很可能是:suspend.target |-systemd-suspend.service |-[custom service] |-sleep.target
所以你的服務在完成它的事情之後執行,這可能是你的問題*。*
systemd-suspend.service
您可以添加到您的服務文件以獲得正確的結果:
Before=systemd-suspend.service
呼叫後,
systemctl daemon-reload
您應該可以使用和systemctl list-dependencies suspend.target --after --all
之間看到您的服務。您的最終操作順序應該是:suspend.target``systemd-suspend.service
suspend.target |-[custom service] |-systemd-suspend.service |-sleep.target