当没有用户登录时运行 systemd 服务

当没有用户登录时运行 systemd 服务

我有一项服务,可在多台实验室机器上运行批处理作业。实验室机器是台式机,我希望仅在当前没有用户登录时运行该服务。这意味着:

  • 当用户登录时,应该停止该服务。
  • 当最后一个用户注销时,应该启动该服务。

我目前的想法是使用Conflicts=,但这存在许多问题:

  • 当最后一个用户注销时,该服务不会再次启动。
  • 手动启动服务将导致强制注销所有用户。
  • 我不知道如何全局化实例化服务(即我需要Conflicts=user@*.service

我该如何定义这样的 systemd 服务而不出现上述问题?

答案1

手动启动服务将导致强制注销所有用户。

不要在您的服务中使用,而是Conflicts=创建一个新的 systemd 目标vacant.target

[Unit]
Description=units that should run when users aren't logged in

[Install]
WantedBy=multi-user.target

您可能希望批处理作业或其他任何内容在 systemd 启动后、用户登录前运行。如果是这样,请启用新目标:systemctl enable vacant.target。也许您对缺少 感到疑惑Conflicts=,并且之前尝试过,您会想:

我不知道如何将实例化服务整合在一起(例如,我需要 Conflicts=user@*.service)

Conflicts=以基本相同的方式影响冲突和冲突的单元。无法进行通配,因此请使用以下命令创建一个插件:systemctl edit '[email protected]'

[Unit]
Conflicts=vacant.target

[Service]
ExecStopPost=+/usr/local/bin/vacancy

请注意每次注销后运行脚本的附加部分,它解决了另一个问题:

当最后一个用户注销时,该服务不会再次启动。

由于领先的+,该脚本/usr/local/bin/vacancy以在 systemd 单元上运行的权限运行:

#!/bin/bash
# Start vacant.target if the list of logged-in users is empty.
[[ -z $(users) ]] && systemctl start vacant.target

无论您想在没有用户登录时运行什么服务、计时器或其他单元,请将其集成到单元文件中:

[Unit]
StopWhenUnneeded=yes

[Install]
WantedBy=vacant.target manual.target

最后,启用您的单元将触发它与 vacant.target 的其余部分一起运行。这StopWhenUnneeded=yes将阻止手动启动该单元。要解决此问题,请创建manual.target

[Unit]
Description=units that normally run when users aren't logged in

使用 手动运行您的单位systemctl start manual.target

相关内容