..

硬盘健康自动化监控: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_CountSSD 磨损均衡接近最大 P/E 值时危险
Media_Wearout_IndicatorNAND 寿命百分比越低越好

SMART 属性的 Raw 值(原始值)和 Value(归一化值)需要一起看。Value 通常初始为 100,随着磨损逐渐降低到阈值以下时,硬盘报告故障。

脚本设计

最初的想法是解析 smartd state 文件或 attrlog csv,省去每次运行直接调用 smartctl 的开销。但实践中发现:

  1. smartd state 文件格式不稳定,不同版本输出不一致
  2. attrlog 需要额外配置,不是每台机器都有
  3. 解析绕来绕去反而增加了复杂度

最终方案:所有 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 资源,不能频繁跑。策略如下:

  1. 短自检(Short test):耗时约 2 分钟,每隔 ≥3 月跑一次
  2. 长自检(Long test):耗时较长(几小时),每隔 ≥12 月跑一次
  3. 长自检优先:如果已过期超过一年,先安排长自检

调度脚本每天定时运行,检查每块硬盘上次自检时间,按需启动。

$ 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 的组合,可以构建一套完整的硬盘健康监控体系。核心原则:在故障发生前发现异常

参考链接