Mac 电池健康度查询:ioreg 命令与 macOS 27 报错修复

本文最后更新于 2026年9月25日 凌晨

在 MacBook 上查看电池健康度,不需要安装第三方软件:system_profiler 可以读取 macOS 报告的最大容量、健康状态和循环次数,ioreg 则适合查看更底层的电池容量字段。

macOS 27 更新说明(2026-09-25): 升级后,我在 M2 Max、macOS 27.0 上重新运行旧的 ioreg 容量计算命令,遇到了 awk: division by zero。本机的 AppleRawMaxCapacity 已没有输出,DesignCapacity 位于 BatteryData 字典内,原有字段提取逻辑需要修改。下文提供修正版,并保留旧字段兼容写法。

本文先给出可直接复制的查询命令,再解释报错原因、容量比与系统最大容量的区别,以及健康度长期不变的可能原因。不同机型和系统版本的字段可能不同,文中样本不代表所有设备。

查询电池健康度

系统最大容量

打开 macOS 的“终端”(Terminal),运行系统自带的命令:

1
system_profiler SPPowerDataType

在输出中找到 Health Information(健康信息),本次测试的相关结果为:

1
2
3
4
Health Information:
Cycle Count: 582
Condition: Normal
Maximum Capacity: 82%
字段 含义 本次样本
Cycle Count 电池循环次数 582 次
Condition 系统报告的电池健康状态 Normal(正常)
Maximum Capacity 系统报告的最大容量百分比 82%

如果只是日常查看电池健康度,读这份系统报告即可。它显示的最大容量与菜单栏里的“当前剩余电量”含义不同。

ioreg 容量估算

如果想查看电池容量相对设计容量的比例,在提供 NominalChargeCapacity 的设备上运行:

1
ioreg -rn AppleSmartBattery -w 0 | tr ',{' '\n' | awk -F= '/"NominalChargeCapacity"[[:space:]]*=/ {c=$2+0} /"DesignCapacity"[[:space:]]*=/ {d=$2+0} END {if(c>0 && d>0) printf "容量比估算: %.1f%%\n", c/d*100; else {print "未读取到有效的电池容量"; exit 1}}'

2026-09-25 本机一次读取的输出为 容量比估算: 79.1%,计算过程是 4808 ÷ 6075 × 100%。

容量比估算不等于 macOS 报告的最大容量。 本次分别得到 79.1% 和 82%,下文解释两者的区别。如果缺少上述字段,可以使用旧字段兼容脚本。

macOS 27 命令修复

旧命令假设容量字段都各占一行,再用 awk 的 $NF 取最后一列。但在本次 macOS 27.0 的输出中,相关数据已经是这样的结构(仅截取部分字段):

1
2
3
"CycleCount" = 582
"BatteryData" = {"FullChargeCapacity"=4658,"NominalChargeCapacity"=4808,"MaxCapacity"=100,"DesignCapacity"=6075,"CurrentCapacity"=80}
"FedDetails" = ({"FedDesignCapacity"=0,...})

这会遇到三个问题:

  • 没有 AppleRawMaxCapacity,原命令的分子没有有效数据。
  • DesignCapacity 在一整行字典里,$NF 取到的并不是单独的容量数字。
  • /DesignCapacity/ 还会匹配 FedDesignCapacity;这些字段并不是这里要读取的电池设计容量。

所以,报错来自字段解析失败,不能据此认为电池的设计容量真的变成了 0。

把旧命令和修改后的处理方式放在一起,会更容易看出区别:

flowchart TB
    accTitle: macOS 27 上旧脚本报错与新脚本处理方式
    accDescr: 本机电池字段变化后,旧脚本读取失败且未检查分母,导致除零。新脚本拆分文本并精确匹配容量字段,检查有效值后再计算容量比。
    A["macOS 27.0 本机输出<br/>电池字段与旧脚本假设不同"]
    A --> B["旧脚本<br/>依赖 AppleRawMaxCapacity<br/>用整行末列提取设计容量"]
    B --> C["字段缺失或误读<br/>分母转成 0,未检查就相除<br/>division by zero"]
    A --> D["新脚本<br/>按分隔符拆分文本<br/>精确匹配容量字段"]
    D --> E{"容量与设计容量<br/>都大于 0?"}
    E -->|是| F["计算容量比<br/>本次样本约 79.1%"]
    E -->|否| G["提示未读到有效容量<br/>停止计算"]
    classDef source fill:#eff6ff,stroke:#2563eb,color:#1e3a5f
    classDef problem fill:#fff1f2,stroke:#e11d48,color:#881337
    classDef fixed fill:#f0fdf4,stroke:#16a34a,color:#14532d
    class A source
    class B,C problem
    class D,E,F,G fixed

图中描述的是本机的兼容性变化;上面的一行命令按这条流程处理。

这里先用 tr 将逗号和左花括号替换成换行,再以 = 分隔键和值;匹配时保留字段两侧的双引号,避免误读 FedDesignCapacity。最后检查分子、分母都大于 0,缺少字段时给出提示,不继续做除法。-w 0 则避免长字典被终端宽度截断。

旧字段兼容

如果想同时输出容量与循环次数,并兼容仍提供 AppleRawMaxCapacity 的设备,可以用下面的展开版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ioreg -rn AppleSmartBattery -w 0 | tr ',{' '\n' | awk -F= '
/"NominalChargeCapacity"[[:space:]]*=/ {nominal=$2+0}
/"AppleRawMaxCapacity"[[:space:]]*=/ {raw=$2+0}
/"DesignCapacity"[[:space:]]*=/ {design=$2+0}
/"CycleCount"[[:space:]]*=/ {cycle=$2+0; hasCycle=1}
END {
capacity = nominal > 0 ? nominal : raw
field = nominal > 0 ? "NominalChargeCapacity" : "AppleRawMaxCapacity"
if (capacity <= 0 || design <= 0) {
print "未读取到有效的电池容量,请检查 AppleSmartBattery 输出"
exit 1
}
printf "容量字段: %s | 容量: %d mAh | 设计容量: %d mAh | 循环次数: %s | 容量比估算: %.1f%%\n", field, capacity, design, (hasCycle ? cycle " 次" : "未读取到"), capacity/design*100
}'

这段脚本优先使用 NominalChargeCapacity,缺少有效值时才尝试 AppleRawMaxCapacity,并明确打印使用的字段。它们的含义不应被视为完全相同,跨设备或跨版本记录数据时,要同时保存字段名。不要用值为 100 的 MaxCapacity 替代 mAh 容量,也不要拿当前剩余电量去算健康度。

旧版脚本的输出截图如下,其中 81.6% 只是当时所选字段算出的容量比:

旧版 ioreg 脚本计算容量比为 81.6% 的历史输出

两种数值为何不同

本次读取时,两种方式得到的结果如下。这是 2026 年更新文章时的样本,与文末 2025 年的检测经历、旧截图不是同一次测量。

方式 数值来源 本次结果
ioreg 配合上面的一行命令 NominalChargeCapacity / DesignCapacity,即 4808 / 6075 79.1%
system_profiler SPPowerDataType macOS 报告的 Maximum Capacity 82%

Apple 将“最大容量”定义为电池容量相对于全新时容量的比例。system_profiler 读取的是系统报告的结果;我们的 ioreg 命令则只是选取两个容量估计字段相除,不能据此还原系统的完整计算过程。Apple:关于搭载 Apple 芯片的 Mac 笔记本电脑中的电池健康管理

因此,79.1% 和 82% 不同,不能简单归因于四舍五入,也不能据此认定系统数据过期、或者前者更准确。日常查看健康状态,可以优先参考系统报告;研究容量变化时,再记录 ioreg 的字段和数值。它们也都不同于菜单栏里的“当前剩余电量”。

健康度更新机制

我还遇到了另一个现象:系统的最大容量长期停留在 82%,但平时正常使用电池,循环次数也在增加。这是不是说明健康度“卡住了”?

重新运行 system_profiler 是重新读取系统数据,不是要求系统立即重新估算健康度。 Apple 的用户支持文档没有承诺每次充满、每个循环或每天都会改变这个百分比。

采样与长期平滑

Apple 公开的 PowerManagement 源码 可以帮助理解这种现象。下面描述的是该固定版本的实现,不能保证与本次测试的 macOS 27.0 完全一致,更不能直接当成对某台机器的诊断。

在这份实现中,容量估计并不是每读一次数据就更新显示值:

  1. 筛选容量样本。 满充容量读数需要发生变化,并通过温度、电流等检查,才会被计入样本。
  2. 跨过评估窗口。 默认时间常量 为 24 小时,还需要有合格样本才能推进计算,并不是每天到点就改一次百分比。
  3. 平滑历史数据。 默认权重近似为:新容量估计 = 旧容量估计 × 90.9% + 本轮样本均值 × 9.1%。
  4. 处理显示百分比。 常规路径还有保留历史较低百分比以及保留容量修正等逻辑,显示结果并不是直接把某次容量读数除以设计容量。

下面用一组假设容量把这个过程串起来。这是上述固定版本公开源码的简化示意,不保证与 macOS 27 的实际实现完全一致。

flowchart TB
    accTitle: 公开源码中的容量采样、平滑与百分比处理
    accDescr: 容量读数经过筛选与累计,满足默认评估间隔且存在合格样本后,将历史估计与本轮样本均值加权平滑,再进行百分比处理。图中容量为假设值,不代表 macOS 27 的完整实现。
    B["筛选并累计电池上报的合格样本<br/>检查容量变化、温度、电流等"]
    B --> C["达到评估条件<br/>超过默认 24 小时间隔<br/>且累计样本非空"]
    C --> D["本轮样本均值:假设 4800 mAh"]
    D -->|权重 9.1%| F["平滑后的容量估计<br/>约 4982 mAh"]
    E["历史容量估计:假设 5000 mAh"] -->|权重 90.9%| F
    F --> G["百分比换算与显示处理<br/>常规路径限制回升等<br/>整数百分比可能保持不变"]
    classDef sample fill:#eff6ff,stroke:#2563eb,color:#1e3a5f
    classDef history fill:#fff7ed,stroke:#ea580c,color:#7c2d12
    classDef result fill:#f0fdf4,stroke:#16a34a,color:#14532d
    class B,C,D sample
    class E history
    class F,G result

这里的 90.9% 和 9.1% 是计算权重,不是健康度,也不是放电比例。举个假设例子:

1
2
3
旧容量估计:5000 mAh
本轮样本均值:4800 mAh
新容量估计:5000 × 0.909 + 4800 × 0.091 ≈ 4982 mAh

新的观测会逐渐影响长期估计,而不是立刻把 5000 改成 4800。因此,内部容量估计可能已经变化,界面的整数百分比仍然不变。

这些机制只能解释“为什么可能不变”。仅凭循环次数增加、系统显示 82%、容量比约 79.1%,无法分辨是内部估计仍在更新但显示未变,还是内部估计很久没有更新。 也不能反过来认定长期停在某个数值就一定正常。

手动刷新与校准

目前没有找到 Apple 面向普通用户提供的“立即重新计算电池健康度”命令。下面几个操作,也需要区分各自的含义:

操作 能说明什么
重新运行 ioreg 或 system_profiler 重新读取当前数据,不保证触发重新估算
正常使用电池、正常充电 可以提供新的观测,但是否采纳、是否改变百分比取决于系统
安装系统更新 Apple 表示更新后可能重新校准最大容量,没有保证每次都会发生
充到 100% Apple 说明系统偶尔充满是为了保持剩余电量估计准确,不能等同于强制刷新健康度

后两点分别见 Apple 的最大容量说明 和 优化电池充电说明。

如果本来就经常使用电池,没有必要为了刷新数字刻意增加循环,更不用反复放电到关机。Apple 也明确说明,锂电池不需要完全放空再充电。Apple:为什么使用锂离子电池

想继续观察时,可以在日常使用中记录日期、系统版本、循环次数、所用容量字段和系统最大容量,再结合相近负载下的续航变化一起看;单次读数不足以判断估计是否停止更新。

电池字段与命令

ioreg 用于查询 macOS 的 I/O 注册表。电池相关属性位于 AppleSmartBattery,下面是旧版输出截图:

ioreg 输出 AppleSmartBattery 电池属性的旧版截图

下面是旧截图中的部分字段。不同机型、系统版本的字段位置和单位可能不同,不能直接把所有 Capacity 都当成 mAh。

电量与充电状态

字段 值 说明
CurrentCapacity 100 当前电量百分比(100% 表示满电)
MaxCapacity 100 此例为电量刻度上限,不代表健康度为 100%
FullyCharged Yes 是否已充满电
IsCharging No 当前是否在充电
ExternalConnected Yes 是否连接了电源适配器
ExternalChargeCapable Yes 电源适配器是否支持充电

容量与硬件信息

字段 值 说明
DeviceName "bq40z651" 电池控制器芯片型号(TI 的 BQ40Z651 电量计)
DesignCapacity 6075 电池设计容量(单位:mAh)
NominalChargeCapacity 5107 电池报告的标称满充容量估计(此例单位为 mAh),不是当前剩余电量
CycleCount 216 电池循环次数(216 次)
DesignCycleCount9C 1000 设计循环次数参考值,不代表到达该次数就无法使用
Temperature 3061 按 Smart Battery 的 0.1 K 格式换算为 32.95°C
Serial "F8Y3******LTAR" 电池序列号

温度换算为 3061 / 10 - 273.15 = 32.95°C。这里依据的是 Apple 驱动中的 macOS 分支 和 Smart Battery 规范 的 0.1 K 单位,不应直接除以 100 当成摄氏度。

筛选充电状态

如果我们想过滤看看电池是否在充电,配合 grep 我们过滤一下:

1
ioreg -n AppleSmartBattery -r | grep -E "CurrentCapacity|FullyCharged|IsCharging|ExternalConnected"

使用 grep 筛选当前电量、充满状态与电源连接状态

你也可以再优化一下:

1
2
# 提取为 key = value
ioreg -n AppleSmartBattery -r | grep -Eo '"CurrentCapacity" = [0-9]+|"FullyCharged" = \w+|"IsCharging" = \w+|"ExternalConnected" = \w+'

将 AppleSmartBattery 的充电状态提取为键值对

ioreg 参数速查

在终端运行 man ioreg 可以查看本机手册。除了查询电池,ioreg 也能查看其他设备的信息,常用选项如下:

选项 说明
ioreg -l 显示所有设备的完整属性(比较长)
ioreg -p IODeviceTree 查看设备树(类似 Linux 的 lspci)
ioreg -p IOService 默认平面,显示服务层设备信息
ioreg -c IOService 显示匹配 IOService 类及其子类的对象属性
ioreg -k BatteryPercent 查找包含 BatteryPercent 属性的设备(如电池信息)
ioreg -n AppleSmartBattery 显示名为 AppleSmartBattery 的设备信息
ioreg -a 以 XML 格式输出,适合脚本解析
ioreg -rn AppleSmartBattery -d 1 以匹配的电池对象为根,仅显示该层节点
ioreg -rn AppleSmartBattery -w 0 查看电池属性,不按终端宽度截断输出

ioreg 查询 macOS IODeviceTree 设备树的终端输出

常见问题

MaxCapacity 的含义

MaxCapacity=100 不代表电池健康度为 100%。在本文设备的输出里,它是电量刻度的上限,不能替代以 mAh 表示的容量。日常查看健康度,应读取 system_profiler 的 Maximum Capacity。

读不到容量怎么办

先运行 ioreg -rn AppleSmartBattery -w 0 查看实际字段。如果只有 AppleRawMaxCapacity,使用上面的旧字段兼容脚本;如果没有电池对象或两个容量字段都没有有效值,就无法使用本文公式计算。此时可检查 system_profiler SPPowerDataType 是否提供电池健康信息,不要改用当前剩余电量凑出一个百分比。

权限与工具要求

本文查询命令使用 macOS 自带的 system_profiler、ioreg、tr 和 awk,本次测试不需要 sudo 或额外安装软件。它们只读取数据,不会主动执行电池校准。


测试背景与参考

这篇文章最初写于 2025 年。当时发现 2021 款 MacBook Pro 的电池不耐用,就去 Apple Store 做了检测:检测得到的容量比例为 82%,系统设置显示的却是 86%。这是当时的经历,与本文 2026 年更新时的 M2 Max 样本不是同一次测量。

2025 年 MacBook Pro 系统设置显示的电池健康度为 86%

我最初从 Stack Overflow 上的 ioreg 电池信息讨论 了解到相关用法,后来又通过 coconutBattery 注意到了“容量与设计容量之比”的展示方式。

coconutBattery 展示电池容量与设计容量的旧版界面

2026 年升级系统后,旧命令报错促使我重新检查字段和计算口径,也修正了原文“更真实的健康度”这一说法:能读到更底层的数据,并不代表相除后的结果就比系统更准确。本文保留旧截图用于对照,数值和字段以自己的设备为准。

文中的更新机制说明引用了 Apple 的官方支持文档与固定版本公开源码,链接已附在相关段落中。继续阅读其他 Mac 使用经验,可以查看Mac 软件与技术经验分享。

如果本篇教程对你有帮助,欢迎加入开发者交流群:812198734,一起交流学习。

支持创作

制作教程不易,如果热心的小伙伴,想支持创作,可以加入我们的电圈(还可以解锁远程协助、好友位😃):

WebChart Recognise

志同道合的小伙伴也是知音难觅。

  • 开发者爱好群: 👉 如果你对云服务器、CDN、云数据库和Linux等云计算感兴趣,亦或者喜欢编程、设计、产品、运营等领域,欢迎加入我们的开发者爱好群,一起交流学习(目前可能就我一个人?🤔,毕竟才刚刚创建~)。
QQ_Group Recognise

当然,也欢迎在B站、YouTube或微信公众号上关注我们:

MintimateBlog Recognise

更多:



Mac 电池健康度查询:ioreg 命令与 macOS 27 报错修复
https://www.mintimate.cn/2025/05/12/ioregBattery/
作者
Mintimate
发布于
2025年5月12日
许可协议