在 Arch Linux 上,我尝试创建一个运行以下 Bash 脚本的 systemd 服务:
#!/bin/bash
/bin/xbindkeys &
/bin/setxkbmap -layout gb
在一些在线指导下,我创建了一个名为myfirst.service
in 的文件/etc/systemd/system
来存储我的服务。以下是该文件的内容:
[Unit]
Description=Command Service
[Service]
ExecStart=/etc/startupjobscript
User=user1
Type=oneshot
Restart=on-abort
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
该服务应该执行/etc/startupjobscript
,即 Bash 脚本。之后,我启用并启动了该服务:
systemctl enable myfirst
systemctl start myfirst
但由于某种原因它不起作用并显示它根本无法加载和运行。
编辑:这是sudo systemctl 状态 myfirst给我吗:
Warning: The unit file, source configuration file or drop-ins of myfirst.service changed on disk. Run 'systemctl daemon-reload' to reload units.
● myfirst.service - Command Service
Loaded: loaded (/etc/systemd/system/myfirst.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Wed 2020-08-26 21:07:02 BST; 18min ago
Process: 332 ExecStart=/etc/startupjobscript (code=exited, status=255/EXCEPTION)
Main PID: 332 (code=exited, status=255/EXCEPTION)
Aug 26 21:07:01 archlinux systemd[1]: Starting Command Service...
Aug 26 21:07:02 archlinux startupjobscript[337]: Cannot open display "default display"
Aug 26 21:07:02 archlinux systemd[1]: myfirst.service: Main process exited, code=exited, status=255/EXCEPTION
Aug 26 21:07:02 archlinux systemd[1]: myfirst.service: Failed with result 'exit-code'.
Aug 26 21:07:02 archlinux systemd[1]: Failed to start Command Service.
答案1
当运行任何与 X 服务器通信的东西时,systemd 服务会变得有点棘手。有两种主要方法可以做到这一点:
- 运行用户服务
- 设置
$DISPLAY
并避免启动,直到graphical.target
达到。
要将其作为用户服务运行,请myfirst.service
移至~/.config/systemd/system/
.然后删除User=
并设置WantedBy=
为default.target
。 default.target
当用户登录时会到达。有一天,graphical-session.target
当用户登录到桌面环境时将会到达,但目前还不可用。相反,我们会default.target
在用户登录时触发。如果您使用显示管理器,那么在此之前您可能有一个 x 会话。
[Unit]
Description=Command Service
After=default.target
[Service]
ExecStart=/bin/xbindkeys
ExecStartPost=/bin/setxkbmap -layout gb
Type=simple
Restart=on-abort
[Install]
WantedBy=default.target
--user
使用本装置时请务必使用,例如:
systemctl --user daemon-reload
systemctl --user start myfirst.service
systemctl --user enable myfirst.service
要将其保留为系统服务,请保留该文件,/etc/systemd/system/
并且您需要设置环境,以便它可以连接到 X 服务器。最后,一定要成功WantedBy=graphical.target
。这可确保在 X 服务器启动之前它不会尝试连接到 X 服务器。但是我不确定它是否总是成功,因为在您登录之前我不确定 .Xauthority 是否有效。
[Unit]
Description=Command Service
After=graphical.target
[Service]
ExecStart=/bin/xbindkeys
ExecStartPost=/bin/setxkbmap -layout gb
Type=simple
User=user1
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/user1/.Xauthority
Restart=on-abort
[Install]
WantedBy=graphical.target
如果您有多个用户或多个显示器,系统范围的服务就会变得有点奇怪。建议做特定于用户的事情。如果您在桌面环境中,您可以echo $DISPLAY
并echo $XAUTHORITY
弄清楚将这些变量设置为什么。
进行这些更改后,您需要告诉systemd
您在尝试下一个之前阅读它们start
。跑步:
systemctl daemon-reload
如果您一直在尝试,请务必systemctl disable myfirst.service
先尝试,然后当您确定systemctl start myfirst.service
有效时,您就可以了systemctl enable myfirst.service
。 将在或enable
中创建一个符号链接,以便在您重新启动时,您的服务被调用。为了避免在实验状态期间弄乱这些链接,请在准备好测试重新启动之前不要启用它。default.target
graphical.target
/bin/xbindkeys &
注意,我确实对你的 bash 脚本中的那一行有一个奇怪的怀疑。通常会xbindkeys
永远运行吗?如果是这样,您可能需要更改ExecStart=
为:
ExecStart=/bin/xbindkeys
ExecStartPost=/bin/setxkbmap -layout gb
Type=simple
我已经对上面建议的单位进行了这些更改。
这将确保 systemd 直接跟踪进程而不是分叉。因为Type=
未设置为forking
,我怀疑 bash 脚本将结束,并且 systemd 不会跟踪 PID,xbindkeys
将其保留为孤立 PID,并且无法阻止它。如果您xbindkeys
作为其中的一部分离开ExecStart
,那么停止服务将终止 xbindkeys(我认为它现在将无法执行)。在这种情况下,您还需要进行设置,Type=simple
因为oneshot
不再适用。