Linux

暫停前停止systemd服務,恢復後重新啟動

  • November 19, 2020

我想要的是

我有一個 systemd 服務,我想在掛起/關閉之前停止,並在恢復後重新啟動。

系統詳情

系統詳情如下。

$ lsb_release -dc
Description:    Ubuntu 20.04.1 LTS
Codename:   focal

$ systemd --version
systemd 245 (245.4-4ubuntu3.3)
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid

到目前為止我所擁有的

我有兩個服務,myservice-resume.service分別myservice-suspend.service在暫停和恢復時啟動和停止 python 程序。python 腳本向控制 RGB 照明的 SDK 伺服器發出命令。當 on 作為參數傳遞時(如在 ExecStart 中),程序必須在後台執行以繼續發出命令作為循環的一部分。當程序擷取到一個 SIGINT 信號時,照明將關閉並優雅地退出。在此設置中,myservice-suspend.service 在掛起之前觸發,並導致myservice-resume.service由於衝突而停止。

myservice-resume.service

[Unit]
Description=Start myservice-resume.service after suspend and shutdown

[Service]
Type=simple
ExecStart=/path/to/python3 /path/to/script.py on

myservice-suspend.service
[Unit]
Description=Stop myservice-resume.service before suspend and shutdown
Before=suspend.target shutdown.target
Conflicts=myservice-resume.service

[Service]
Type=oneshot
ExecStart=/bin/true

[Install]
WantedBy=suspend.target shutdown.target

在此設置中,我使用、或通過使用 進行系統掛起來啟動服務(和照明)systemctl start myservice-resume.service並成功關閉照明。我想要第一個服務,在系統恢復時自動重新啟動。我想這將涉及在systemctl start myservice-suspend.service``systemctl stop myservice-resume.service``systemctl suspend``myservice-resume.service

$$ Unit $$和$$ Install $$部分,但我無法確定設置它的適當方法。 研究/我嘗試過的

一個相關的文章(Systemd: stop service before suspend, restart after resume *)*暗示我可以通過添加After=suspend.targetmyservice-resume.service. 我已經嘗試過了,但是 systemctl 日誌顯示該單元在恢復時沒有再次啟動。

這篇文章(為掛起/恢復編寫 systemd 單元文件)將 OP 指向 systemd 手冊頁以提出解決方案(並闡明 After/WantedBy 的目的),但我在這裡也找不到解決方案。

After=or的需求Before=最終可以在來自archlinux的範例中看到(像往常一樣,這是一個非凡的幫助來源)。基於該連結,有兩種解決方案可以在掛起和恢復時執行命令。

一種方法是使用兩個單位,例如mysyssuspendmysysresume。以下範例只是將date命令執行到 syslog,以便我們可以看到它們何時被啟動:

/etc/systemd/system/mysyssuspend.service

[Unit]
Before=suspend.target
[Service]
Type=simple
StandardOutput=syslog
ExecStart=/bin/date +'mysyssuspend start %%H:%%M:%%S'
[Install]
WantedBy=suspend.target

/etc/systemd/system/mysysresume.service

[Unit]
After=suspend.target
[Service]
Type=simple
StandardOutput=syslog
ExecStart=/bin/date +'mysysresume start %%H:%%M:%%S'
[Install]
WantedBy=suspend.target

像往常一樣,在創建單元文件之後執行 asystemctl daemon-reload和。systemctl enable mysyssuspend mysysresume

第一個單元Before依賴於掛起目標,並在電腦進入掛起狀態時執行。第二個單元同樣具有After依賴關係,並在恢復時執行。

另一種方法將所有命令放在一個單元中: /etc/systemd/system/mysuspendresume.service

[Unit]
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
StandardOutput=syslog
RemainAfterExit=yes
ExecStart=/bin/date +'mysuspendresume start %%H:%%M:%%S'
ExecStop=/bin/date +'mysuspendresume stop %%H:%%M:%%S'
[Install]
WantedBy=sleep.target

這適用於StopWhenUnneeded=yes,因此在沒有活動服務需要時停止服務。sleep 目標也有StopWhenUnneeded,所以當它完成時它將執行ExecStop我們的單元。這RemainAfterExit是必要的,以便我們的單位仍然被視為活躍,即使在ExecStart完成之後。

我在具有 systemd 版本 237 的 Ubuntu 18.04.5 上測試了這兩種方法,它們似乎都可以正常工作。


與其嘗試將您的需求合併到上述工作機制中,不如使用其中一個來停止/啟動獨立單元可能更實用。例如,使用第二種方法並添加一個mylongrun服務:

/etc/systemd/system/mysuspendresume.service

[Unit]
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
StandardOutput=syslog
RemainAfterExit=yes
ExecStart=-/bin/date +'my1 %%H:%%M:%%S' ; /bin/systemctl stop mylongrun ; /bin/date +'my2 %%H:%%M:%%S'
ExecStop=-/bin/date +'my3 %%H:%%M:%%S' ; /bin/systemctl start mylongrun ; /bin/date +'my4 %%H:%%M:%%S'
[Install]
WantedBy=sleep.target

/etc/systemd/system/mylongrun.service

[Unit]
Description=Long Run
[Service]
Type=simple
StandardOutput=syslog
ExecStart=/bin/bash -c 'date +"my11 %%H:%%M:%%S"; while sleep 2; do date +"my12 %%H:%%M:%%S"; done'
ExecStop=/bin/bash -c 'date +"my13 %%H:%%M:%%S"; sleep 10; date +"my14 %%H:%%M:%%S"'
[Install]
WantedBy=multi-user.target

通過開始mylongrun然後關閉蓋子來測試它會給出以下 journalctl 條目:

09:29:19 bash[3626]: my12 09:29:19
09:29:21 bash[3626]: my12 09:29:21
09:29:22 systemd-logind[803]: Lid closed.
09:29:22 systemd-logind[803]: Suspending...
09:29:22 date[3709]: my1 09:29:22
09:29:22 systemd[1]: Stopping Long Run...
09:29:22 bash[3715]: my13 09:29:22
09:29:23 bash[3626]: my12 09:29:23
09:29:25 bash[3626]: my12 09:29:25
09:29:27 bash[3626]: my12 09:29:27
09:29:29 bash[3626]: my12 09:29:29
09:29:31 bash[3626]: my12 09:29:31
09:29:32 bash[3715]: my14 09:29:32
09:29:32 systemd[1]: Stopped Long Run.
09:29:32 date[3729]: my2 09:29:32
09:29:32 systemd[1]: Reached target Sleep.
09:29:33 systemd[1]: Starting Suspend...

我們可以看到長時間執行的停止命令 ( sleep 10) 正確完成。在恢復時,將再次啟動長期執行命令:

09:35:12 systemd[1]: Stopped target Sleep.
09:35:12 systemd[1]: mysuspendresume.service: Unit not needed anymore. Stopping.
09:35:12 systemd[1]: Reached target Suspend.
09:35:12 date[3813]: my3 09:35:12
09:35:12 systemd[1]: Started Long Run.
09:35:12 date[3817]: my4 09:35:12
09:35:12 bash[3816]: my11 09:35:12
09:35:14 bash[3816]: my12 09:35:14
09:35:16 bash[3816]: my12 09:35:16
09:35:18 bash[3816]: my12 09:35:18

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