You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

POSIX电池提醒脚本通过cron运行时DBUS地址重启变动如何解决?

使用notify-send和cron实现电池电量提醒时的DBUS动态地址问题

问题背景

我使用i3窗口管理器,没有内置电池状态通知功能,曾多次出现笔记本电量耗尽的情况,因此编写了一个POSIX shell脚本,结合notify-send实现电量提醒,手动调用可正常运行。

脚本代码

#!/bin/sh
percent=`upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep percentage:`
notify-send "battery life" "$percent"

现有定时配置

我通过crontab设置每10分钟执行一次脚本,配置如下:

*/10 * * * * export DISPLAY=:0 ; export DBUS_SESSION_BUS_ADDRESS=a; batterystatus.sh

遇到的问题

去掉DBUS_SESSION_BUS_ADDRESS配置项后notify-send无法正常运行,而该地址每次开机都会变动,需要每次开机手动修改crontab配置才能正常使用,需要找到规避该问题的方法。

解决方案

这个问题的本质是cron运行在非会话上下文,默认不会继承桌面会话的DBUS_SESSION_BUS_ADDRESS环境变量,该变量是notify-send调用桌面通知服务的必需参数,且每次桌面会话启动都会生成新的地址,硬编码无法长期生效。
你可以选择以下任意一种方案解决:

方案1:修改脚本自动获取DBUS地址(适配现有cron配置)

在batterystatus.sh开头添加环境变量自动获取逻辑,无需硬编码地址:

#!/bin/sh
# 单显卡桌面环境DISPLAY默认固定为:0
export DISPLAY=:0
# systemd发行版通用DBus地址获取逻辑
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"

# 建议将反引号替换为$()写法,兼容性更好
percent=$(upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep percentage:)
notify-send "battery life" "$percent"

如果你的发行版未使用systemd,可以用以下代码替换DBUS变量导出逻辑,从运行的i3进程中读取环境变量:

export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME i3)/environ | cut -d= -f2-)

修改完成后可将crontab简化为:

*/10 * * * * /绝对路径/到/batterystatus.sh

注意需要给脚本添加执行权限:chmod +x /绝对路径/到/batterystatus.sh,crontab中需填写脚本的完整绝对路径。

方案2:使用i3内置自启循环(i3用户首选,无需额外配置)

直接在i3配置文件(默认路径~/.config/i3/config)中添加以下内容,i3启动时会自动运行定时循环,天然带有完整的会话环境变量,完全不需要处理DBUS相关问题:

exec --no-startup-id while true; do /绝对路径/到/batterystatus.sh; sleep 600; done

修改后重载i3配置(默认快捷键Mod+Shift+C)即可生效,开机自动运行。

方案3:使用systemd用户定时器(替代cron,更易管理)

如果需要更规范的定时任务管理,可以使用systemd用户级定时器,用户级服务默认运行在会话上下文,自动携带所需的环境变量:

  1. 新建服务文件~/.config/systemd/user/batterystatus.service:
[Unit]
Description=电池电量通知服务

[Service]
ExecStart=/绝对路径/到/batterystatus.sh
  1. 新建定时器文件~/.config/systemd/user/batterystatus.timer:
[Unit]
Description=每10分钟运行一次电量检查

[Timer]
OnCalendar=*:0/10
Persistent=true

[Install]
WantedBy=timers.target
  1. 执行命令启用定时器:
systemctl --user enable --now batterystatus.timer

设置完成后定时器会开机自启,运行日志可通过journalctl --user -u batterystatus.service查看。

内容的提问来源于stack exchange,提问作者octo-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 00:57:00