我想要的是

我想要的是

我想要的是

我有一个 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.servicesystemctl stop myservice-resume.service或者使用 进行系统挂起systemctl suspend。我希望第一个服务myservice-resume.service在系统恢复时自动重新启动。我想这将涉及在 [Unit] 和 [Install] 部分中添加一些巧妙的 After/Before/WantedBy 目标,但我无法确定适当的方法来设置它。

研究/我尝试过的

相关帖子(Systemd:挂起前停止服务,恢复后重新启动)暗示我可以配置一个服务来运行After=suspend.target通过添加到 的 Unit 部分来从挂起恢复myservice-resume.service。我已经尝试过此操作,但 systemctl 日志显示该单元在恢复时未再次启动。

这个帖子 (编写用于挂起/恢复的 systemd 单元文件)将 OP 指向 systemd 手册页以提出解决方案(并阐明 After/WantedBy 的目的),但我在这里也找不到解决方案。

答案1

最后可以在以下示例中看到对After=or的需要Before=架构Linux(像往常一样,这是一个非凡的帮助来源)。基于该链接,有两种在挂起和恢复时运行命令的解决方案。

一种方法是使用两个单位,例如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

像往常一样,在创建单元文件后执行systemctl 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,因此当没有活动服务需要时,服务会停止。睡眠目标也有StopWhenUnneeded,因此当它完成时,它将运行ExecStop我们的单元。这RemainAfterExit是必要的,以便我们的单位即使在ExecStart完成后仍然被视为活动的。

我在 Ubuntu 18.04.5 上使用 systemd 版本 237 测试了这两种方法,它们似乎都能正常工作。


与其尝试将您的需求合并到上述工作机制中,不如使用其中之一来停止/启动独立单元可能更务实。例如使用第二种方法,添加一个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

相关内容