我正在尝试为 编写用户级服务redshift,它需要等到 Xorg 启动并运行。我当前的服务文件如下所示:
[Unit]
Description=Redshift
After=graphical.target
[Service]
Environment=DISPLAY=:0
ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr
Restart=always
[Install]
WantedBy=default.target
Run Code Online (Sandbox Code Playgroud)
但是,它似乎尝试在 Xorg 启动之前启动,之后我必须手动启动该服务。我想我使用了错误的After=目标。任何提示?
小智 38
我一直在研究这个,grawity 的答案似乎已经过时了。您现在可以使用作为用户会话的一部分运行的 systemd 设置用户服务。它们可以设置 DISPLAY 和 XAUTHORITY(目前在 Arch、Debian Stretch+ 和 Ubuntu 中)。
这比之前使用桌面自动启动文件的建议更有意义,因为您可以像管理系统级应用程序(重启等)一样进行进程管理。
现在最好的文档是 Arch wiki;系统/用户
TLDR 版本;
~/.config/systemd/user/systemctl --user enable [service](排除 .service 后缀)systemctl --user start [service]以立即开始systemctl --user status [service]来检查它是如何做其他几个有用的命令。
systemctl --user list-unit-files - 查看所有用户单位systemctl --user daemon-reload - 如果您编辑 .service 文件- 之后...
我将大部分会话守护进程升级并转换为 systemd .service 文件。所以我可以添加一些额外的注释。
登录时没有运行服务的默认挂钩,因此您必须自己触发它。我从我的~/.xsession文件中做到这一点。
systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target
Run Code Online (Sandbox Code Playgroud)
第一行将一些环境变量导入 systemd 用户会话,第二行启动目标。我的xsession.target档案;
[Unit]
Description=Xsession running
BindsTo=graphical-session.target
Run Code Online (Sandbox Code Playgroud)
我xbindkeys.service以我为例。
[Unit]
Description=xbindkeys
PartOf=graphical-session.target
[Service]
ExecStart=/usr/bin/xbindkeys -n -f ${HOME}/projects/dotfiles/.xbindkeysrc
Restart=always
[Install]
WantedBy=xsession.target
Run Code Online (Sandbox Code Playgroud)
use*_*686 11
通常的提示是“不要”。 redshift不是系统范围的服务——它会为每个会话有一个单独的实例,它需要知道如何连接到特定会话的 Xorg。
(Xorg 也不是系统服务——只有显示管理器是,它还会为每个会话启动一个单独的 Xorg。//graphical.target会告诉您显示管理器何时准备就绪,但它没有说明 DM 何时真正启动首先 - 或全部 - 显示。)
仅在启动时启动它DISPLAY=:0是不够的,因为不能保证在任何给定时间只有一个显示,也不能保证总是有:0(例如,如果 Xorg 崩溃并留下陈旧的锁文件,下一个将按:1原样运行会认为:0还是被占用);您还需要设置XAUTHORITY文件路径,因为 X11 需要身份验证;并确保redshift在您注销并再次登录时重新启动。
那么如何开始呢?几乎总是,桌面环境有几种方法来启动它自己的会话服务。请参阅一篇较旧的帖子,该帖子已经描述了两个常见的帖子;该~/.xprofile脚本和~/.config/autostart/*.desktop位置。
如果你使用startx,你可以~/.xinitrc用来启动这样的事情。独立的窗口管理器通常有自己的启动/初始化脚本;例如~/.config/openbox/autostart对于 Openbox。
什么是共同所有这些方法是程序从启动内部会议-避免上面列出的所有问题。
该解决方案完全符合问题作者的要求:
它需要等到 Xorg 启动并运行
虽然可能有更好的方法来做到这一点,正如其他用户已经回答的那样,但这是解决此问题的另一种方法。
它类似于 systemd 的systemd-networkd-wait-online.service,它会阻塞直到满足某些条件。一旦该服务启动成功或者超时,依赖它的其他服务就会启动。
根据手册(“文件”部分),X 服务器将创建一个 UNIX 套接字/tmp/.X11-unix/Xn(其中n是显示编号)。
通过监视此套接字的存在,我们可以确定特定显示的服务器已启动。
confirm_x_started.sh:
#!/bin/bash
while [ 1 ]
do
# Check whether or not socket exists
if [ -S /tmp/.X11-unix/X0 ]
then
exit 0
fi
# Adjust timeout according to your needs
if [ $SECONDS -gt 15 ]
then
exit 1
fi
sleep 0.5
done
Run Code Online (Sandbox Code Playgroud)
x_server_started.service:
[Unit]
Description=Monitor X server start
[Service]
Type=oneshot
ExecStart=/path/to/confirm_x_started.sh
[Install]
WantedBy=example.target
Run Code Online (Sandbox Code Playgroud)
现在,启用x_server_started.service与 X 服务器同时启动。
使其他服务(需要启动X服务器)依赖x_server_started.service
附属单位:
[Unit]
Description=Service that needs to have the X server started
Requires=x_server_started.service
After=x_server_started.service
[Service]
ExecStart=/path/to/binary
[Install]
WantedBy=example.target
Run Code Online (Sandbox Code Playgroud)
如果 X 服务器启动没有问题,则x_server_started.service几乎会立即启动,并且 systemd 将继续启动所有依赖于x_server_started.service.
小智 5
这是我刚刚创建的解决方法,以解决尚未可用的问题graphical-session.target(在我的 Kubuntu 16.04 系统上):
~/.config/systemd/user/xsession.target使用以下内容创建:
[单元] 说明 = Xsession 启动并运行 BindsTo=graphical-session.target
告诉 systemd 这个新单元:
$> systemctl --user daemon-reload
Run Code Online (Sandbox Code Playgroud)
xsession.target通过 Ubuntu 16.04 桌面的当前可用机制来控制。~/.config/autostart-scripts/xsession.target-login.sh使用以下内容创建:
#!/bin/bash 如果 !systemctl --user is-active xsession.target &> /dev/null 然后 /bin/systemctl --user 导入环境显示 XAUTHORITY /bin/systemctl --user start xsession.target 菲
~/.config/plasma-workspace/shutdown/xsession.target-logout.sh使用以下内容创建:
#!/bin/bash 如果 systemctl --user 处于活动状态 xsession.target &> /dev/null 然后 /bin/systemctl --user 停止 xsession.target 菲
使脚本可执行:
$> chmod +x ~/.config/autostart-scripts/xsession.target-login.sh $> chmod +x ~/.config/plasma-workspace/shutdown/xsession.target-logout.sh
注意:这两个文件被放置在 KDE 为自动启动和关闭而选择它们的地方。这些文件可能放在其他桌面环境(例如 Gnome)的其他地方 - 但我不知道这些环境。
注意:此解决方法缺乏对多桌面会话的支持。graphical-session.target只要一台机器上只运行一个活动的 X11 会话,它就会正确处理(但对于我们大多数 linux 用户来说就是这种情况)。
graphical-session.target并让它们在登录到您的桌面时干净地运行。例如@mkaito 的单位应该是这样的:
[单元] 说明=红移 PartOf=graphical-session.target [服务] ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr 重启=总是
(不要忘记daemon-reload在编辑你的单位后做一个!)
$> systemctl --user status graphics-session.target
? graphics-session.target - 当前图形用户会话
已加载:已加载(/usr/lib/systemd/user/graphical-session.target;静态;供应商预设:已启用)
活跃:自 Don 2017-01-05 15:08:42 CET 开始活跃;47 分钟前
文档:man:systemd.special(7)
$> systemctl --user status your-unit...
在未来的某一天(它会是 Ubuntu 17.04 吗?)我的解决方法将过时,因为系统会graphical-session.target自行正确处理。在那一天,只需删除自动启动和关闭脚本以及xsession.target- 您的自定义用户单元可能保持不变并且可以正常工作。