如何防止 systemd 在重新启动时停止服务

如何防止 systemd 在重新启动时停止服务

我有以下服务文件,用于打开和关闭外部设备:

[Unit]
Description=Manage the UR controller, turn it off when the system goes down.
Requires=network.target
After=network.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/sbin/ur_boot
ExecStop=/usr/local/sbin/ur_shutdown

[Install]
WantedBy=multi-user.target

它运行良好,但外部设备的启动和关闭时间很长,因此当我重新启动时,需要一段时间才能再次准备就绪。

是否可以告诉 systemd 在重新启动时不要停止我的服务,但仍会停止它以进行定期关闭?

答案1

这个答案太长了,无法发表评论。但我希望它能为你指明一个好的方向。

man systemd.special

   shutdown.target
       A special target unit that terminates the services on system shutdown.

       Services that shall be terminated on system shutdown shall add Conflicts= 
       and Before= dependencies to this unit for their service unit, which is 
       implicitly done when DefaultDependencies=yes is set (the default).

所有服务都隐含地带Conflicts=shutdown.target.因此,当shutdown.target引发时,所有服务都将停止。唯一的例外是如果您添加DefaultDependencies=no.

在其他答案的评论中,您询问reboot.target.

   reboot.target
       A special target unit for shutting down and rebooting the system.

如果我们查看细节,reboot.target我们可以看到它是shutdown.target通过以下方式引发的systemd1-reboot.service

$ busctl introspect \
    org.freedesktop.systemd1 \
    /org/freedesktop/systemd1/unit/reboot_2etarget
...
.Names    "reboot.target" "runlevel6.target" "ctrl-alt-del.target"
.Requires "systemd-reboot.service"

$ busctl introspect \
    org.freedesktop.systemd1 \
    /org/freedesktop/systemd1/unit/systemd_2dreboot_2eservice
...
.DefaultDependencies false
.After               "final.target" "system.slice" "umount.target" "shutdown.target" "systemd-journald.socket"
.Requires            "final.target" "system.slice" "umount.target" "shutdown.target"
.SuccessAction       "reboot-force"

因此,就您的情况而言,您可以添加DefaultDependencies=no[Unit]“避免在重新启动时停止服务”部分,但它也将无法在关机期间停止您的服务。这是因为重新启动包括关闭。


我最好的想法(不确定是否可行)是创建一个服务:

[Unit]
DefaultDependencies=no
Before=reboot.target shutdown.target

[Service]
ExecStart=touch %t/rebooting

[Install]
WantedBy=reboot.target

当启动重新启动时,这将在 ram 中创建一个文件。

然后将您的服务更改为:

ExecStop=/bin/bash -c "test -e %t/rebooting || /usr/local/sbin/ur_shutdown"

当该文件存在时,这将阻止您的ExecStop命令运行。这不会阻止您的ExecStart命令运行,但我希望如果您的外设已经在运行,这将立即返回。

如果您需要避免运行ExecStart,请尝试在非易失性位置创建该文件。

ExecStart=touch %S/rebooting

然后仅在脚本不存在时运行脚本(如果存在则清理它)。

ExecStart=/bin/bash -c "if [ -e %S/rebooting ]; then rm %S/rebooting; else /usr/local/sbin/ur_start; fi"
ExecStop=/bin/bash -c "test -e %S/rebooting || /usr/local/sbin/ur_shutdown"

答案2

对于Linux(即systemd)来说,关闭计算机或重新启动计算机之间没有区别(除了一种状态以计算机停止而结束而另一种状态再次启动计算机这一事实之外,需要注意的是,没有操作系统当我们到达这些状态时正在运行)。所以不,重新启动时您无法保持任何运行(请记住,计算机会崩溃)。

不要与休眠混淆,它使系统停止并保留机器状态的副本(将内存缓存到磁盘)并能够将系统恢复到关闭之前的状态。

在您的情况下,如果您的系统启动时间太长,并且您已经确定了延迟启动的设备,您可能需要检查哪些其他服务依赖于该设备,如果您不考虑的话,也许可以消除依赖关系重要的是,以便在该设备启动时可以继续启动。

相关内容