手动终止完全关闭的 systemd 服务

手动终止完全关闭的 systemd 服务

我有一个在云虚拟机上运行的定期任务。该机器类型非常昂贵,因此我有一个 systemd 单元服务,该服务在启动时启动,运行脚本,然后关闭机器以节省资金。这按设计工作。

我在维护机器时遇到了麻烦,因为如果我登录并发出service [] stop命令,系统当然会立即关闭(正如它应该的那样)。

我认为我应该能够使用OnFailure它,但我也希望系统在脚本因某种原因失败时关闭(而不是在崩溃时让虚拟机旋转)。或者一些用途ExecStop

会有三种情况:

  • 进程正确执行并终止(例如退出代码0),系统电源关闭
  • 进程崩溃(例如退出代码!= 0),系统断电
  • 服务被用户终止/暂停?系统保持开启状态

简单的解决方案是在启动、登录、禁用、重新启动(因为服务已经启动)、执行维护任务然后重新启用之前给服务一分钟的宽限期。但这似乎有点笨拙。服务定义如下,供参考。

[Unit]
Description="Run job"
After=network.target
StartLimitInterval=200
StartLimitBurst=30
OnFailure=systemd-poweroff.service

[Service]
Type=simple
Restart=on-failure
RestartSec=30
ExecStartPre=/bin/sleep 60
ExecStart=/my/script.sh
ExecStopPost=sudo systemctl poweroff -i
User=foo

[Install]
WantedBy=multi-user.target

请注意,由于环境设置而不是任何安全意识,脚本以普通用户身份运行,因此这里使用 sudo (该帐户专门被授予用于关闭电源的无密码 sudo 权限)。

答案1

poweroff不要在操作中运行,而是ExecStopPost将其移动到单独的服务中。也就是说,让您的“运行作业”服务看起来像这样:

[Unit]
Description="Run job"
After=network.target
Requires=my-poweroff.service
Before=my-poweroff.service

[Service]
Type=oneshot
Restart=on-failure
RestartSec=30
ExecStart=/my/script.sh
User=foo

[Install]
WantedBy=multi-user.target

请注意,我们使用的是Type=oneshot而不是Type=simple,因为这样在脚本完成之前服务不会“启动”。这很重要,因为我们通过Requires=/依赖项触发断电Before=;使用Type=simple,该作业和关机作业将开始同时。使用Type=oneshot意味着关闭作业在该服务退出之前不会运行。

然后在 中my-poweroff.service,你有:

[Unit]
ConditionPathExists=!/run/nopoweroff

[Service]
Type=simple
ExecStart=/usr/bin/systemctl poweroff -i

现在,如果您想在“运行作业”服务完成之前poweroff阻止。touch /run/nopoweroff

相关内容