Systemd

如何在網路關閉之前觸發 systemd 單元掛起?

  • January 25, 2022

(庫存 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 下掛起是如何進行的:

  1. 掛起是由一個程序(例如systemctl suspend)向 logind 發送一個 dbus 呼叫啟動的。
  2. Logind 然後向任何收聽的人發送 PrepareToShutdown dbus 信號。
  3. 然後 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.servicethen sleep.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

引用自:https://unix.stackexchange.com/questions/337853