在我的 Gentoo Linux 上,使用 dunstify 作为通知守护进程,使用 StumpWM 作为窗口管理器,我编写了以下 bash 脚本,用于告知我电池状态:
#!/bin/bash
#This script notifies you if your battery is under 80% and puts the laptop to sleep in 5min if it is under 50% and isn't plugged in within that time.
if ! [ -z "$(acpi -b | cut -c 25)" ] && [[ $(acpi -b | cut -c 25) -lt 8 ]] && ! [[ "$( acpi -b | cut -c 28)" == "%" ]]
then if ! [ -z "$(acpi -b | cut -c 25)" ] && [[ $(acpi -b | cut -c 25) -lt 5 ]] && ! [[ "$(acpi -b | cut -c 28)" == "%" ]]
then dunstify "Battery <50" "Battery under 50%, will sleep in 5min."
sleep 5m
if ! [ -z "$(acpi -b | cut -c 25)" ] && [[ $(acpi -b | cut -c 25) -lt 5 ]] && ! [[ "$(acpi -b | cut -c 28)" == "%" ]]
then sudo systemctl suspend
fi
else dunstify "Battery <80" "Battery under 80%."
fi
fi
当我手动触发它时,它可以正常工作。但是,它应该每 10 分钟左右由 systemd 定期触发一次,并在电池电量不足时通知我。因此,我编写了以下 systemd-service:
[Unit]
Description=Checks your battery.
RefuseManualStart=no
RefuseManualStop=yes
[Service]
Type=oneshot
ExecStart=/bin/battery
如果电池电量高于 80%,服务将顺利完成,这是理所当然的。但是,如果电池电量低于 80%,服务将因错误而退出。查看日志,我发现以下内容:
░░ A start job for unit battery.service has begun execution.
░░
░░ The job identifier is 79311.
Jul 10 16:02:54 gentoolaptop battery[537360]: Connecting to D-Bus failed: Unable to autolaunc>Jul 10 16:02:54 gentoolaptop systemd[1]: battery.service: Main process exited, code=exited, s>░░ Subject: Unit process exited
░░ Defined-By: systemd
░░ Support: https://gentoo.org/support/
░░
░░ An ExecStart= process belonging to unit battery.service has exited.
我一直尝试将其作为用户服务运行,并收到此消息;作为系统服务运行,并被告知未设置 XDISPLAY 和 XAUTHORITY。为什么在作为服务触发时无法发送消息?
D-Bus 会话总线的工作方式与 X 服务器类似 - 每个系统可以有多个,因此客户端必须知道要连接的套接字地址,即它们需要
DBUS_SESSION_BUS_ADDRESS=
哪个大致相当于DISPLAY=
。(这与具有全局套接字地址但仅允许您与系统服务对话的系统总线不同。)
因此,您必须让 ..._BUS_ADDRESS 与 DISPLAY 和 XAUTHORITY 一起显示
systemctl --user show-environment
;最简单的方法可能是确保您的 ~/.xinitrc(或其他 X 启动脚本)在启动会话总线systemctl --user import-environment [...]
后调用。启动会话总线有两种方式:
传统的“会话总线”:在 /tmp 下随机生成的地址。
Systemd 风格的“用户总线”:位于固定位置 $XDG_RUNTIME_DIR/bus (/run/user/UID/bus)。
最好将您的系统切换到第二种方法 - 我不完全确定在 Gentoo 中如何做到这一点,但我认为它需要使用 useflag 构建 dbus
systemd
,以便它可以安装用户单元,并dbus.service
从您的 ~/.xinitrc 或其他 X 启动脚本中删除任何对 dbus-launch 或 dbus-run-session 的使用。dbus.socket
然后,您的 systemd --user 实例将自动在 /run/user 下的“众所周知”位置启动总线(在您的 X 会话、所有 tty 会话和服务之间共享);一些 D-Bus 客户端将能够默认在那里找到它,但 pam_systemd 也会将 DBUS_SESSION_BUS_ADDRESS 设置为该位置,并且 systemd --user 本身将自动知道它。
我的用户 systemd-service 无法通过 dbus 进行通信的问题似乎是我用来
startx
启动窗口管理器但没有该行在我的 中
.xinitrc
,我显然应该将其放在窗口管理器执行之前的位置。现在设置了此行后,服务就可以正常工作了。