我想用我的自定义程序(类似信息亭的设置)替换我的 Xsession,以前我只是STARTUP
在文件中设置变量,.xsessionrc
例如:
STARTUP='/path/to/my/program'
现在我想将我的程序包装为 systemd 服务,以利用一些 systemd 功能,例如日志记录、可配置的自动重启等。与之前的设置一样,我希望避免运行第 3 方会话和窗口管理器,但我仍然必须运行一些东西来保持会话活动,所以我使用了:
STARTUP='systemd-run --user --scope /path/to/my/program'
然而它仍然不是一个方便的 systemd 单元,最后我得到了:
STARTUP='systemd-run --user --scope --unit my-session sleep inf'
并为我的程序定义了一个服务单元来运行:
[Unit]
Description=My service
BindsTo=my-session.scope
Requisite=my-session.scope
After=my-session.scope
[Service]
Type=exec
ExecStart=/path/to/my/program
Restart=always
[Install]
WantedBy=my-session.scope
一般来说,这个设置就像一个魅力,但是依赖于动态生成的范围名称对我来说似乎很笨重,而且有时需要在会话重新启动时进行隐式清理,例如:
systemctl reset-failed my.service my-session.scope
因为systemd
抱怨my-session.scope
已经存在。
因此,我正在寻找一种同步运行 systemd 服务的方法,systemd-run --scope
但同时重新使用现有的单元文件,而不是动态生成一个文件。
PS:我尝试过以下方法,但它无法正常工作(中断 systemctl 不会中断托管服务):
systemctl start --wait my-session.target
答案1
最后找到了几个合适的配置:
a) 将正在运行的服务标记为StopWhenUnneeded
并使用Wants
属性systemd-run --scope
:
.xsessionrc:
STARTUP='systemd-run --user --scope --property Wants=my.service sleep inf'
我的服务:
[Unit]
Description=My service
StopWhenUnneeded=yes
[Service]
Type=exec
ExecStart=/path/to/my/program
Restart=always
这确实是最小的解决方案,并且可以完成所有需要的事情,但是不可能my.service
手动启动。如果需要:
b) 引入中间体my-session.target
并声明my.service
为PartOf=my-session.target
:
.xsessionrc:
STARTUP='systemd-run --user --scope --property Wants=my-session.target sleep inf'
我的服务:
[Unit]
Description=My service
PartOf=my-session.target
[Service]
Type=exec
ExecStart=/path/to/my/program
Restart=always
[Install]
WantedBy=my-session.target
我的会话.目标:
[Unit]
Description=My session
StopWhenUnneeded=yes
RefuseManualStart=yes
RefuseManualStop=yes
c) 最后值得注意的是,systemd-run
并不禁止使用“仅自动”属性,例如BoundBy
/ ConsistsOf
,因此可以执行以下操作:
.xsessionrc
STARTUP='systemd-run --user --scope --property BoundBy=my.service --property Wants=my.service sleep inf'
我的服务:
[Unit]
Description=My service
[Service]
Type=exec
ExecStart=/path/to/my/program
Restart=always
我会考虑使用这些属性作为 hackish 并且可能是一个错误。但也许有人会发现它有用。