最可靠方式是直接读取/sys/class/power_supply/下动态遍历的电池目录(如bat0/bat1),因其绕过d-bus和acpi依赖,避免upower服务未运行或acpi bios支持缺失导致的unknown状态及解析不稳定问题。

Linux 下直接读 /sys/class/power_supply/ 是最可靠、无依赖的方式,比 upower 或 acpi 更底层、更准,尤其在轻量发行版或 Wayland 环境中不会失灵。
为什么 upower 有时显示 “unknown” 或不更新
upower 依赖于 D-Bus 和 UPower 服务进程,而该服务可能未运行(如 minimal systemd 环境)、被禁用,或与当前电源设备驱动不兼容。常见现象是执行 upower -i /org/freedesktop/UPower/devices/battery_BAT0 后返回 state: unknown 或 percentage: unknown。
- 检查服务状态:
systemctl --user is-active upower(用户级)或systemctl is-active upower(系统级) - 若为 inactive,启用它:
sudo systemctl enable --now upower,但注意:某些嵌入式或容器化环境根本无法运行该服务 - 更稳的替代方案是绕过 D-Bus,直读 sysfs
从 /sys/class/power_supply/BAT0 手动读取电量字段
几乎所有现代 Linux 内核都通过 power_supply 子系统暴露电池信息,路径通常为 /sys/class/power_supply/BAT0(部分机器可能是 BAT1、axp288_battery 等,可用 ls /sys/class/power_supply/ 确认)。
-
cat /sys/class/power_supply/BAT0/capacity→ 当前剩余百分比(整数,如73) -
cat /sys/class/power_supply/BAT0/status→ 充电状态(Charging/Discharging/Full/Not charging) -
cat /sys/class/power_supply/BAT0/energy_now和energy_full→ 以微瓦时(µWh)为单位的实际能量值(比capacity更适合计算剩余时间) -
cat /sys/class/power_supply/BAT0/voltage_now→ 实时电压(单位微伏 µV),可用于判断老化程度
注意:power_now 并非所有电池都支持;若读取报错 No such file or directory,说明该字段未由驱动导出,跳过即可。
acpi 命令的适用边界和坑
acpi 依赖 ACPI BIOS 表(主要是 BAT0 的 _BIF 和 _BST 控制方法),在老旧笔记本、某些 ARM 设备(如 Surface Pro X)、或 BIOS 关闭 ACPI 电池支持时会失效,典型错误是 No support for device type: battery 或直接无输出。
- 安装:
sudo apt install acpi(Debian/Ubuntu)或sudo dnf install acpid(Fedora) - 基础用法:
acpi -b显示简略状态,acpi -i显示详细信息 - 但不要依赖它做自动化脚本——因为它的输出格式不稳定(例如不同版本可能多空格、换行位置不同),解析易出错
- 若
acpi -b输出rate information unavailable,说明 BIOS 没提供放电率,此时无法估算剩余时间
写一个可靠的电量监控脚本要注意什么
真正实用的脚本(比如用于 i3status、polybar 或定时提醒)必须容忍字段缺失、权限拒绝、多电池等情况。
- 先探测电池目录:
for bat in /sys/class/power_supply/BAT*; do [[ -d "$bat" ]] && echo "$bat"; done | head -n1 - 用
grep -q "Discharging"判断是否在掉电,比单纯看capacity变化更准 - 读取前加
2>/dev/null || echo "N/A"避免因权限或字段不存在导致脚本中断 - 不要硬编码
BAT0—— ThinkPad 可能是BAT0,MacBook Linux(via Asahi)可能是apple-battery,Chromebook 可能是gsb-battery
最常被忽略的是:有些设备(如双电池工作站)会同时存在 BAT0 和 BAT1,且内核可能只让其中一个上报容量,另一个始终显示 0 —— 这不是 bug,是硬件设计如此,需主动跳过 capacity 为 0 的条目。











