![当没有用户登录时运行 systemd 服务](https://linux22.com/image/1511040/%E5%BD%93%E6%B2%A1%E6%9C%89%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E6%97%B6%E8%BF%90%E8%A1%8C%20systemd%20%E6%9C%8D%E5%8A%A1.png)
我有一项服务,可在多台实验室机器上运行批处理作业。实验室机器是台式机,我希望仅在当前没有用户登录时运行该服务。这意味着:
- 当用户登录时,应该停止该服务。
- 当最后一个用户注销时,应该启动该服务。
我目前的想法是使用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
。