SMART属性监控实战:smartctl巡检预警,避免硬盘数据丢失 那年冬天一块运行了三年的某品牌企业盘在凌晨两点突然亮起了红灯。不是监控平台直接报警而是我的巡检脚本注意到Reallocated_Sector_Ct这个属性在24小时内从3涨到了15。盘还在正常读写smartctl -H的结果也还是 PASSED但我们没有赌运气直接安排了数据迁移和换盘。两天后这块盘彻底失联。这之后我一直坚持用smartctl 7.3做硬盘巡检重点盯5个 SMART 属性并自己定义故障预警阈值和告警脚本。这套方案到今天已经跑了两年多帮我躲过了至少三次可能造成数据丢失的事故。这篇就把它掰开揉碎讲清楚。1. SMART原理和smartctl 7.3为什么值得上手1.1 SMART到底在盘里干了什么很多人把 SMART 当成一个“预测软件”这是误解。SMARTSelf-Monitoring, Analysis and Reporting Technology本质上是硬盘固件里的一组计数器。盘片在读写过程中一旦发生某些物理层面的异常比如扇区读不出来、磁头重试次数变多、马达温度波动固件就会把这些事件记到特定编号的属性里。你的系统不参与计数它只是定期把数字读出来。所以 SMART 给出的不是“这块盘还能活多久”的直接答案而是一堆“健康痕迹”。好的解读方式是看属性的变化趋势和速率而不是只看某个瞬间的值。机械盘和固态盘都是这个逻辑区别在于关键属性不同。比如机械盘最怕盘片磨损和磁头异常固态盘则更关心闪存块擦写次数。1.2 smartctl 7.3的安装与基本用法smartctl 是 smartmontools 工具包里的核心命令7.x 版本对 SATA、SAS、NVMe 都覆盖得比较全大部分 Linux 发行版仓库里都能直接装。# Debian / Ubuntu apt install smartmontools # CentOS / RHEL / Rocky yum install smartmontools装完先确认版本smartctl -V我要求团队里统一用 7.3 及以上原因是 7.3 开始对 NVMe 设备的新属性支持更完整而且--json输出格式更稳定方便写脚本直接解析。早期版本也可以用但不建议停留在 5.x那个时代解析新盘属性经常出错。先看盘符和基本信息lsblk -o NAME,SIZE,MODEL,SERIAL smartctl -a /dev/sda-a是--all输出完整的 SMART 信息包括属性表、自检日志、错误日志。日常巡检我基本只用这一条。快速看健康状态用smartctl -H /dev/sda这个命令只输出一行 PASSED 或 FAILED适合“一眼扫过”的场景但说实话PASSED只代表没有属性跌破厂商阈值绝不等于盘安全。后面我会专门讲这个问题。如果设备是 NVMe 固态盘直接smartctl -a /dev/nvme0即可。如果服务器用 SAS 盘可能要指定设备协议smartctl -a -d scsi /dev/sda再比如硬盘接在 USB 硬盘盒里桥接芯片支持 SAT 指令的话smartctl -a -d sat /dev/sdc这些参数在写脚本时必须考虑到否则同样的代码在不同机器上表现完全不同。2. 5个关键属性逐个拆解SMART 属性表里往往有几十行但真正值得你天天盯的没几个。我这里按故障预警优先级给你拆5个并解释为什么是它们。2.1 属性5Reallocated_Sector_Ct 重映射扇区计数这个属性在 smartctl 输出里的样子通常是ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE 5 Reallocated_Sector_Ct 0033 100 100 005 Pre-fail Always - 3理解它的关键是“重映射”三个字。硬盘出厂时会预留一小部分备用扇区当固件发现某个扇区读写不稳定会把它的物理地址映射到备用区客户端继续访问原逻辑地址也不受影响。属性5的 RAW 值就是累计发生过多少次这样的重映射。机制上第一次重映射可能是偶发原因比如一个临时性坏道备用扇区替换后就稳定了RAW 停在1不再涨。这种情况盘还能继续用。但如果 RAW 值持续增大尤其是每天都有新的增长那通常说明盘片表面镀层退化、磁头高度异常或者盘内有颗粒脱落坏道正在扩散。我给团队的判读标准很简单RAW 0健康。RAW 1~4需要记录基线第二天看有没有继续涨。RAW ≥ 5进入预警状态。单日增量 ≥ 3或者一周增量 ≥ 10直接进入“计划换盘”状态。注意不要只盯VALUE。很多盘的 VALUE 初始是100重映射十几次后还是100只有跌到 THRESH比如5以下才会被判 FAILED。等你在 VALUE 上看到下降趋势盘可能已经坏到没法正常读写了。RAW 才是真实的坏块痕迹。2.2 属性197Current_Pending_Sector 当前待处理扇区这个属性描述的是“固件已经注意到某个扇区不对劲但还没定性”的状态。通俗讲就是盘遇到一个扇区重试了好几次读取不确定是暂时性问题还是永久性坏块于是先挂起等下次有机会再验证。这一点和属性5有本质区别。属性5是已经确认坏了用备用区顶上了。属性197则可能走向两个结果后续某次读取成功该扇区从 pending 列表里移除RAW 值下降。后续确认读不出来转入重映射属性5增加197减少。所以197的 RAW 值可以波动不能只看单次数值要看它是否持续存在并增长。197 Current_Pending_Sector 0032 100 100 000 Old_age Always - 2我对这个属性的要求是RAW 大于0就亮黄灯。哪怕是1只要它持续存在超过24小时说明盘片表面确实有物理损伤而不是瞬时干扰。如果是持续增长比如从2涨到5再涨到9基本不用怀疑盘在走向不可逆的损坏。2.3 属性198Offline_Uncorrectable 离线不可纠正错误198 Offline_Uncorrectable 0032 100 100 000 Old_age Always - 1这可能是最容易被忽略但最危险的属性之一。它统计的是硬盘在执行后台离线扫描offline scan时发现的、完全无法读取且无法纠错的扇区数。注意普通读写可能还没碰到这些扇区所以盘看起来一切正常但后台自检已经把“死扇区”记在案了。如果这个属性持续上涨说明盘片不是偶发坏道而是大面积的介质退化。它的出现往往比属性5更晚但也更致命。198一旦出现都不该当作小事。RAID 卡和 Linux 内核的 md raid 在后台一致性校验时最容易触发这类扇区暴露。我的处置优先级是197 198 5。198只要出现非0值就按危险处理。先做全盘镜像或移动关键数据不要等属性5爆发。2.4 属性199UDMA_CRC_Error_Count 接口校验错误这个属性刚开始容易被当成“盘要坏了”实际它跟盘体健康没有直接的因果关系。UDMA_CRC 错误是 SATA 接口在传输数据时接收方计算出的 CRC 校验值和发送方不一致产生的计数。绝大多数情况下是物理链路问题SATA 数据线松动或氧化。硬盘笼背板触点接触不良。热插拔托盘没有插紧。电源供电不稳导致信号电平异常。磁盘控制器或主板 SATA 控制器异常。典型输出199 UDMA_CRC_Error_Count 0032 200 200 000 Old_age Always - 1检查思路应该是如果只有199在涨其他关键属性都正常第一反应绝对不是换盘而是换线、重插、换托架、换背板接口。处理完继续观察这个属性不太会自己清零只要不再涨就算排除。如果重插后还在快速涨才能怀疑接口电路或盘体控制板。我见过一块盘两天内 CRC 从0涨到2000最后确认是机柜理线时把 SATA 线折了直角。换线后一切正常。这种问题如果判断成盘体故障会白白浪费一块好盘。2.5 属性194Temperature_Celsius 盘体温度机械硬盘对温度极其敏感。温度过高会使磁头臂的机械伺服特性漂移加剧盘片热膨胀同时加速润滑油蒸发。冷静看待这个属性的人不多很多玩家只看表面数字。smartctl 对温度的表示有点绕。一部分盘 RAW 值就是当前摄氏度比如40另一部分盘会显示二进制补码比如184代表当前40度224-18440。别去死记公式直接看 VALUE 或者用--json输出里的.temperature.current字段工具已经换算好了。194 Temperature_Celsius 0032 040 040 000 Old_age Always - 40我对机械盘的温度标准35℃ ~ 45℃最佳工作区间。46℃ ~ 50℃可以接受但要关注机柜通风。51℃ ~ 55℃黄灯。持续在这种温度下运行会明显缩短寿命。55℃ 以上红灯。属于过热运行状态必须停机排查风道。需要说明的是近几年氦气盘的工作温度上限比空气盘高一些45℃~50℃也是常见工况。但“高一些”不等于没上限超过55℃依然非常危险。笔记本里的2.5寸盘因为结构紧凑日常50℃左右是常态不能直接套桌面盘的标准。3. 故障预警阈值怎么设3.1 为什么厂商阈值不能直接信任每块盘固件里都存着一组 THRESH阈值。当 VALUE 跌到 THRESH 以下smartctl -H就会输出 FAILED。但问题恰恰在这里厂商阈值是为“让盘在彻底报废前给你最后一次警报”设计的不是为“让你从容备份数据”设计的。举个例子某块企业盘的 Reallocated_Sector_Ct 阈值是5当 VALUE 从100开始掉要重映射上百个扇区后才会跌破5。可等你看到 VALUE 明显下降时盘片的坏道已经扩散得相当严重全盘镜像可能都要抢时间做。再比如某些盘固件对部分属性根本不参与健康判定哪怕 RAW 已经飙到几百smartctl -H依旧显示 PASSED。所以我们要做的不是去掉厂商阈值而是在它之上叠一套自己的“业务预警阈值”在盘真正 FAILED 之前就提前介入。3.2 一套直接可用的预警阈值表这是我目前生产环境在用的基准值按“预警”和“危险”两级划分。这里的数值针对机械硬盘主要用属性5、197、198、199、194。属性数值类型预警危险说明5 Reallocated_Sector_CtRAW≥5≥20预警后记录24小时增量197 Current_Pending_SectorRAW≥1≥10只要非0就持续观察198 Offline_UncorrectableRAW≥1≥4出现非0即缩短换盘周期199 UDMA_CRC_Error_CountRAW≥5及持续增长≥100优先排查链路而非盘体194 Temperature_CelsiusRAW/当前值≥50≥55连续1小时以上这组阈值不是一个死数字。容量越大的盘坏道扩散影响面越大阈值可以适当收紧。比如 8T 以上大容量盘重映射超过10个就该走换盘流程。而一些老型号的企业盘本身通电寿命高重映射阈值放到30也不是不行关键还是看“增速”。属性变化速率往往比绝对值更具指示性。我自己的经验是如果连续两天的巡检发现属性5或197都在增长无论是否达到危险阈值都应该进入“主动迁移数据”流程。增长趋势才是硬道理。3.3 用脚本把阈值变成凌晨2点的告警看盘不能靠人肉定时执行命令要让它定期自动跑。下面是我在用的巡检脚本核心部分依赖smartctl 7.x和jq解析 JSON 输出。#!/usr/bin/env bash # 硬盘SMART巡检告警脚本 set -uo pipefail DISKS(sda sdb sdc sdd) STATE_DIR/var/lib/smart-alert ALERT_LOG/var/log/smart-alert.log MAIL_TOopsexample.com mkdir -p $STATE_DIR T_REALLOC_WARN5 T_REALLOC_CRIT20 T_PENDING_WARN2 T_PENDING_CRIT10 T_CRC_WARN5 T_TEMP_WARN50 T_TEMP_CRIT55 for DISK in ${DISKS[]}; do # 对SAS盘或USB盘需要加 -d scsi / -d sat这里按SATA盘处理 DATA$(smartctl -A -j /dev/$DISK 2/dev/null) [ -z $DATA ] { echo 获取SMART信息失败: $DISK $ALERT_LOG; continue; } REALLOC$(echo $DATA | jq -r .attributes[] | select(.id5) | .raw.value) PENDING$(echo $DATA | jq -r .attributes[] | select(.id197) | .raw.value) CRC$(echo $DATA | jq -r .attributes[] | select(.id199) | .raw.value) TEMP$(echo $DATA | jq -r if .temperature.current then .temperature.current else null end) # 判断重映射 if [ $REALLOC -ge $T_REALLOC_CRIT ]; then echo [CRIT] $DISK 重映射扇区达 $REALLOC $ALERT_LOG elif [ $REALLOC -ge $T_REALLOC_WARN ]; then # 对比昨天的值判断是否仍在增长 LAST_FILE$STATE_DIR/$DISK.realloc LAST_VAL$(cat $LAST_FILE 2/dev/null || echo 0) if [ $REALLOC -gt $LAST_VAL ]; then echo [WARN] $DISK 重映射扇区为 $REALLOC, 持续增长 $ALERT_LOG fi fi echo $REALLOC $STATE_DIR/$DISK.realloc # 判断待处理扇区 if [ $PENDING -ge $T_PENDING_CRIT ]; then echo [CRIT] $DISK 待处理扇区达 $PENDING $ALERT_LOG elif [ $PENDING -ge $T_PENDING_WARN ]; then echo [WARN] $DISK 待处理扇区为 $PENDING $ALERT_LOG fi # 判断CRC错误 if [ $CRC -ge $T_CRC_WARN ]; then echo [WARN] $DISK CRC校验错误累计 $CRC, 请检查线缆与背板 $ALERT_LOG fi # 判断温度 if [ $TEMP ! null ]; then if [ $TEMP -ge $T_TEMP_CRIT ]; then echo [CRIT] $DISK 当前温度 $TEMP 度已过危险阈值 $ALERT_LOG elif [ $TEMP -ge $T_TEMP_WARN ]; then echo [WARN] $DISK 当前温度 $TEMP 度请检查风道 $ALERT_LOG fi fi done if [ -s $ALERT_LOG ]; then # 日志有内容才通知到人 mailx -s SMART巡检异常 $(hostname) $(date %F) $MAIL_TO $ALERT_LOG : $ALERT_LOG fi这个脚本有几个细节是实测总结出来的用-A而不是-a只输出属性表减少解析负担。--json输出字段在不同盘上可能有差异但attributes[].id是稳定的所以我按 id 筛选属性。温度字段用.temperature.current如果在某个设备上不存在脚本会兜底成 null宁可漏报这条也不因为格式问题中断整个巡检。日志文件有内容才发邮件避免每一天都轰炸收件箱。状态文件保存上次重映射值用于判断“是否仍在增长”。这是判断是否换盘最关键的信息。设置计划任务0 2 * * * /usr/local/bin/smart_alert.sh /dev/null 21选择凌晨2点是经验半夜业务低峰SMART 读取不会干扰磁盘 IO而且如果盘真的有问题一早醒来就能看到邮件留给白天足够的处置时间。4. 真实环境中踩过的坑与排查实录4.1 服务器上读不到SMART属性我在一台服务器上执行smartctl -a /dev/sda结果直接提示smartctl 7.3 2022-02-28 r5083 [x86_64-linux-5.10.0] (local build) Copyright (C) 2002-22, Bruce Allen, Christian Franke, www.smartmontools.org /dev/sda: Unknown USB bridge SMART support is: Ambiguous—device appears to be USB-attached.排查后发现是 USB 硬盘盒的桥接芯片比较老不走标准 SAT 协议。这时可以强制指定smartctl -a -d sat /dev/sda如果还不行很可能这个 USB 桥接根本不透明SMART 信息无法拿到只能换设备验证。另一类常见场景是服务器带 RAID 卡系统看到的是/dev/sda这个虚拟盘SMART 信息默认不直通。这种情况要看 RAID 卡型号比如某常见服务器阵列卡需要用类似这种方式访问物理盘smartctl -a -d megaraid,0 /dev/sda其中0是 RAID 组内的物理盘编号。不同厂商的阵列卡指令不同有的用-d 3ware,0有的走-d cciss,0。写巡检脚本前先在每台机器上手动试一遍确认能读出物理盘属性再上自动化。4.2 CRC错误暴涨换盘还是换线有一块 4T 数据盘某天脚本报警UDMA_CRC_Error_Count已经累计到 700 多。按之前的经验这更像是链路问题但用户业务方很着急要求立刻换盘。我坚持先做链路排查重插服务器这一端 SATA 线。换一根全新的 SATA 线。换硬盘笼上的一个槽位。排查电源接口是否松动。结果换线后再观察两天CRC 计数稳定没有继续涨盘体其他属性也全部正常。如果当时直接换盘这块硬盘会带着“误判”的历史标签退役浪费一块健康盘。顺便说一句CRC 错误在 SATA 盘上普遍不会清零重启也不会。所以判断标准永远是“是否还在增加”而不是“当前值是否为0”。只要它不涨对数据拓扑的影响力可以忽略。4.3 温度和自检的误报处理刚开始跑脚本时某台机器一天之内收到20多封高温邮件因为脚本把阈值设低了而那台机器正好是高性能计算节点机箱风道被硬件挡住了一部分。后来加了两个保护逻辑连续两次巡检间隔24小时都超温才告警。邮件告警合并到同一封标题写明盘号和温度不刷屏。还有一次误报来自smartctl -A -j里对某块企业盘温度字段的解析。那块盘的temperature.current字段是空的但temperature.drive_trip有值脚本第一版直接取了raw.value解析出来的数字不对。后来统一加if-else兜底优先用temperature.current取不到才尝试属性194。4.4 NVMe与SAS设备的属性差异这里单独提醒一下上面的5个属性主要针对 SATA 机械盘。NVMe 固态盘的 SMART 属性体系完全不同比如常用的是Percentage Used按设计寿命估算的消耗百分比。Available Spare备用块剩余比例。Temperature主控温度超过85℃会触发过热保护。Media and Data Integrity Errors介质和数据错误计数。Error Information Log Entries错误日志条目数。SAS 盘的属性名称又和 SATA 盘略有差异。所以脚本如果要跨设备类型巡检需要先根据设备类型选择对应的属性集合不能拿同一套字段直接套。我在生产环境里是分开的机械盘走上面那套脚本NVMe 走另一套逻辑各自独立跑 cron互不干扰。最后再分享一点心得我在实际部署这套方案时体会到SMART 预警最难的不是读懂某个属性而是克服“盘看起来还能用”的侥幸心理。属性5回到0或者197消失不见不等于之前的异常没有发生过。每一次重映射、每一个 pending 扇区都是盘片上留下的物理痕迹它们不会说谎。我个人的做法是只要某块盘出现任何一次危险属性非0且持续增长就立刻把它标记为“待退役”不管smartctl -H是否 PASSED。数据迁移的成本永远低于数据恢复的成本这句话在硬盘故障这件小事上被验证了太多次。