硬盘健康自动化监控:SMART 从入门到日报
背景
服务器硬盘是整台机器最脆弱的部件之一。机械硬盘(HDD)有磁头碰撞、坏道扩散的风险,固态硬盘(SSD/NVMe)有寿命耗尽、写入放大的问题。等到系统报 I/O error 再处理,往往已经来不及了。
SMART(Self-Monitoring, Analysis and Reporting Technology)是硬盘自带的健康监测功能,能提前预警故障。本文将分享一套完整的自动化方案:从读取 SMART 数据、Python 解析,到集成 cron 日报推送。
📝 本文在 AI 辅助下完成,内容经人工审核验证。
SMART 基础
查看硬盘列表
$ lsblk -d -o NAME,TYPE,SIZE
NAME TYPE SIZE
sda disk 500G
sdb disk 2T
读取 SMART 数据
ATA 硬盘(SATA/SAS):
# 查看所有属性
$ sudo smartctl -A /dev/sda
# 健康状态概览
$ sudo smartctl -H /dev/sda
# 历史错误记录
$ sudo smartctl -l error /dev/sda
# 自检记录
$ sudo smartctl -l selftest /dev/sda
NVMe 硬盘走的是 NVMe 协议,参数略有不同,但 smartctl --all 能统一处理:
$ sudo smartctl --all /dev/nvme0n1
关键属性解读:
| 属性 | 含义 | 警戒值 |
|---|---|---|
Reallocated_Sector_Ct | 重映射扇区数 | > 0 就要注意,> 100 建议更换 |
Power_On_Hours | 通电时长 | 用来估算剩余寿命 |
Temperature_Celsius | 当前温度 | > 60°C 需要加强散热 |
Current_Pending_Sector | 待重映射扇区 | > 0 说明有潜在坏道 |
Wear_Leveling_Count | SSD 磨损均衡 | 接近最大 P/E 值时危险 |
Media_Wearout_Indicator | NAND 寿命 | 百分比越低越好 |
SMART 属性的 Raw 值(原始值)和 Value(归一化值)需要一起看。Value 通常初始为 100,随着磨损逐渐降低到阈值以下时,硬盘报告故障。
脚本设计
最初的想法是解析 smartd state 文件或 attrlog csv,省去每次运行直接调用 smartctl 的开销。但实践中发现:
- smartd state 文件格式不稳定,不同版本输出不一致
- attrlog 需要额外配置,不是每台机器都有
- 解析绕来绕去反而增加了复杂度
最终方案:所有 ATA 属性通过 smartctl -A 实时读取,NVMe 用 sudo smartctl --all。
def get_ata_attributes(device):
"""解析 smartctl -A 输出,返回有序的属性列表"""
result = subprocess.run(
["sudo", "smartctl", "-A", f"/dev/{device}"],
capture_output=True, text=True, timeout=10
)
# 解析 ID, NAME, FLAG, VALUE, WORST, THRESH, TYPE, RAW_VALUE
...
def get_nvme_attributes(device):
"""解析 NVMe SMART 日志"""
result = subprocess.run(
["sudo", "smartctl", "--all", f"/dev/{device}"],
capture_output=True, text=True, timeout=10
)
# 解析 NVMe 独有的字段:percentage_used, temperature, 等
...
为了避免每次都要输入密码,需要配置 sudo 免密:
# /etc/sudoers.d/smartctl
your_user ALL=(ALL) NOPASSWD: /usr/sbin/smartctl
Quick vs All 模式
脚本提供了多种运行模式,适应不同场景:
| 模式 | 耗时 | 内容 |
|---|---|---|
quick | ~0.08s | 只读 cached 状态(温度、通电时间等) |
smart | ~0.15s | 完整 SMART 属性(全部 ATA/NVMe 属性) |
software | ~3.5s | 软件版本、已安装包、内核信息 |
all | ~3.5s | 以上全部 |
日报使用 quick 模式,周报使用 all 模式,平衡效率和完整性。
自动化调度
三阶段自检策略
硬盘自检(Self-test)会消耗 I/O 资源,不能频繁跑。策略如下:
- 短自检(Short test):耗时约 2 分钟,每隔 ≥3 月跑一次
- 长自检(Long test):耗时较长(几小时),每隔 ≥12 月跑一次
- 长自检优先:如果已过期超过一年,先安排长自检
调度脚本每天定时运行,检查每块硬盘上次自检时间,按需启动。
$ sudo smartctl -l selftest /dev/sda
# 读取最后一条记录的时间戳,判断是否过期
日报/周报
日报每天推送 quick 模式结果,周报每周推送 all 模式综合报告。使用 cron 定时调度,结果推送到消息平台(支持 webhook、邮件、bot 等多种方式)。
日报:每天 → quick 模式 → 消息推送
周报:每周 → all 模式 → 详细报告
自检调度:每天 → 按需启动自检
踩坑记录
1. NVMe 参数兼容
早期的 smartctl 版本(6.x)对 NVMe 属性的输出格式不同,需要用 -l nvme-log 而非 --all。目前 smartctl 7.x+ 已统一,但兼容老版本时要注意。
2. 多硬盘并发
多块硬盘时逐块执行 smartctl 会显著延长耗时。可以用 concurrent.futures.ThreadPoolExecutor 并行读取:
with ThreadPoolExecutor(max_workers=4) as executor:
results = executor.map(get_ata_attributes, sata_devices)
quick 模式下多盘并发的总耗时可以控制在 0.2s 以内。
3. sudo 权限
如果使用 cron 自动执行,需要注意 smartctl 需要 root 权限。配置 /etc/sudoers.d/smartctl 免密执行,并在 cron 脚本中指定完整路径。
从数据到可读性
原始 SMART 数据是数字堆叠,需要转化成可读的结论。例如:
/dev/sda: Generic SSD 500G
温度: 41°C ✅
通电: 10000h
重映射: 0 ✅
待重映射: 0 ✅
寿命: 95% ✅
对于异常值,脚本会标记颜色和说明:
/dev/sdb: Generic HDD 2T ⚠️
温度: 52°C ⚠️ 偏高 (>50°C)
通电: 8000h
重映射: 12 ⚠️ 存在坏道
待重映射: 4 ⚠️ 潜在坏道
建议: 尽快备份数据,考虑更换硬盘
总结
通过 smartctl + Python + cron 的组合,可以构建一套完整的硬盘健康监控体系。核心原则:在故障发生前发现异常。