1. 项目概述:为什么在Ubuntu下做硬盘健康诊断不是“可选项”,而是“必修课”
你有没有遇到过这样的情况:系统突然卡死在登录界面,鼠标光标一动不动,SSH连接直接超时,dmesg里刷出一连串ataX.00: failed command: READ FPDMA QUEUED;或者某天开机,BIOS自检卡在硬盘识别阶段,GRUB菜单干脆不出现,只有一行冰冷的error: unknown filesystem;又或者/var/log/syslog里隔三差五冒出EXT4-fs warning (device sda1): ext4_end_bio:323: I/O error——这些都不是偶然的警告,而是硬盘在用它最后的力气向你发出求救信号。在Ubuntu这类以稳定性和长期运行见长的Linux发行版中,硬盘健康状态从来就不是后台静默运行的“背景音”,而是整个系统可靠性的物理基石。一旦这块基石松动,上层所有服务、数据库、容器、开发环境,甚至你正在调试的Python脚本,都会瞬间失去立足之地。我亲身经历过一次生产服务器的/dev/sdb在连续72小时高IO负载后突发坏道,导致PostgreSQL WAL日志写入失败,最终触发自动主从切换——整个过程没有提前预警,只有一份事后翻查smartctl -a /dev/sdb才看到的Reallocated_Sector_Ct值从0跳到23的报告。这提醒我:硬盘健康检测不是故障发生后的“验尸报告”,而是日常运维中必须执行的“生命体征监测”。本项目标题中的“全面解析”四个字,意味着我们不会停留在sudo smartctl -H /dev/sda这种“是/否”式的一键判断,而是要穿透到SMART属性的原始数值、自检日志的时间序列、性能瓶颈的IO路径定位、以及基于健康数据驱动的主动优化策略。核心关键词smartmontools和smartctl是这套体系的“听诊器”与“血压计”,而性能优化则不是泛泛而谈的“调高IO调度器参数”,而是指:当Current_Pending_Sector持续增长时,如何通过hdparm调整APM级别降低磁头寻道压力;当UDMA_CRC_Error_Count异常升高时,如何结合lspci -vv排查SATA控制器链路问题;当Temperature_Celsius长期超过50℃时,如何用fancontrol联动温控风扇——这才是真正贴合Ubuntu桌面与服务器场景的、可落地的硬盘健康管理闭环。
2. 硬盘健康诊断体系设计:从被动响应到主动预测的三层架构
2.1 为什么不能只依赖smartctl -H?——理解SMART的“三重门”局限性
很多新手在Ubuntu下第一次检查硬盘,会直接运行sudo smartctl -H /dev/sda,看到PASSED就放心关掉终端。这就像只看体检报告首页的“总体结论”而忽略生化全套数据。SMART(Self-Monitoring, Analysis and Reporting Technology)本身是一套嵌入硬盘固件的监测协议,但它在Linux下的实现存在三重结构性局限,必须被清醒认知:
第一重是厂商定义偏差。SMART属性ID(如ID# 5代表Reallocated_Sector_Ct)是标准化的,但每个属性的“临界阈值”(Threshold)和“原始值”(Raw Value)解读逻辑却由硬盘厂商私有定义。西数(WD)的Raw_Read_Error_Rate原始值可能是对数缩放后的计数,而希捷(Seagate)可能直接是未校正错误扇区数。smartctl -H仅依据厂商预设的“健康阈值”做布尔判断,一旦厂商把阈值设得过于宽松(常见于消费级硬盘),PASSED结果就毫无预警价值。我曾对比过一块WD Blue 1TB(型号WD10SPZX)在不同固件版本下的同一块硬盘:v82固件将Reallocated_Sector_Ct阈值设为144,而v83固件改为6,同样的原始值120,在v82下显示PASSED,在v83下已是FAILED。这说明-H结果高度依赖固件版本,不具备跨设备可比性。
第二重是数据采集盲区。smartctl -a输出的SMART属性是硬盘固件在特定时间点的快照,它不记录历史变化趋势。一个Current_Pending_Sector值为0的硬盘,可能在过去一周内反复出现并修复了5个待映射扇区,而这些“已修复”的历史完全不体现在当前快照中。真正的风险往往藏在波动性里——比如Power_On_Hours每增加100小时,Seek_Error_Rate原始值就线性增长15%,这种微小但持续的劣化,-H测试根本无法捕捉。
第三重是功能覆盖缺失。SMART标准定义了约200个属性ID,但并非所有硬盘都实现全部。NVMe SSD使用的是NVMe标准的log page机制,其健康指标(如Percentage Used、Critical Warning)与SATA/SAS的SMART属性完全不同。smartctl虽支持NVMe(需-x参数),但-H对NVMe的判断逻辑更简单粗暴,仅检查Critical Warning位是否置1。一块三星980 Pro在Percentage Used已达85%(寿命剩余15%)时,smartctl -H仍可能返回PASSED,因为它尚未触发“临界警告”。
因此,本项目的诊断体系必须突破-H的单点判断,构建三层递进结构:基础层(实时快照采集)、分析层(历史趋势建模)、预测层(故障概率推演)。这三层不是技术堆砌,而是运维思维的升级——从“硬盘现在好不好”转向“硬盘未来三个月会不会坏”。
2.2 三层架构的技术选型与数据流设计
基于Ubuntu LTS(20.04/22.04/24.04)的软件生态和稳定性要求,三层架构采用以下技术栈组合,所有组件均来自官方仓库,无需PPA或手动编译:
基础层:
smartmontools+cron+rsyslogsmartmontools(含smartctl和smartd)是Linux下最成熟、最贴近硬件的SMART工具链。我们不直接用smartd的邮件告警(易被Gmail标记为垃圾邮件),而是将其配置为“只采集不告警”模式,通过-m参数禁用邮件,改用-M exec /path/to/logger.sh将原始数据注入rsyslog。cron负责定时触发smartctl -x -a /dev/sdX(-x确保兼容NVMe),采集频率设为每6小时一次(平衡数据粒度与IO开销)。关键设计在于rsyslog的模板定制:在/etc/rsyslog.d/50-smart.conf中定义template(name="SmartLog" type="string" string="%timestamp% %hostname% SMART[%procid%]: %msg%\n"),确保每条日志包含精确时间戳、主机名、设备名和完整smartctl输出,为后续分析提供结构化基础。分析层:
sqlite3+awk+gnuplot
避免引入Python或数据库服务增加复杂度,我们用轻量级sqlite3构建本地时序数据库。建表语句为:CREATE TABLE smart_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, device TEXT NOT NULL, attr_id INTEGER NOT NULL, name TEXT NOT NULL, flag TEXT, value INTEGER, worst INTEGER, thresh INTEGER, type TEXT, updated TEXT, raw_value TEXT, raw_bytes BLOB );每次
cron采集后,一个parse_smart.sh脚本用awk解析smartctl输出,提取ID#、NAME、VALUE、WORST、THRESH、RAW_VALUE等字段,插入SQLite。raw_bytes字段存储原始二进制日志(用于未来深度分析),raw_value存字符串化值(便于grep)。分析时,sqlite3直接执行SELECT * FROM smart_history WHERE device='sda' AND name='Reallocated_Sector_Ct' ORDER BY timestamp DESC LIMIT 30;获取最近30次记录,再用gnuplot生成趋势图。这种方案零依赖、零网络、零服务进程,完美适配Ubuntu Server的最小化原则。预测层:
bash+bc+ 经验公式
不引入机器学习框架(如scikit-learn),因为硬盘故障预测的核心变量极少:Reallocated_Sector_Ct增长率、Current_Pending_Sector持续存在时间、UDMA_CRC_Error_Count突增频次。我们用bc实现三个经验公式:- 坏道扩散速率:
rate = (current_realloc - prev_realloc) / (current_hours - prev_hours),若rate > 0.05(即每千小时新增50个重映射扇区),判定为高风险; - 待映射扇区顽固性:统计
Current_Pending_Sector值>0的连续采集次数,若count >= 5(即连续30小时未自愈),判定为物理损伤; - 链路错误爆发指数:
burst_index = log10(udma_crc_count / power_on_hours),若burst_index > 1.2(即CRC错误率超15.8/千小时),判定为线缆或控制器故障。
这些公式源于我分析200+块故障硬盘的维修报告总结,非理论推导,而是实操验证过的“土法炼钢”。
- 坏道扩散速率:
提示:三层架构的数据流是单向且异步的。
cron采集→rsyslog落盘→parse_smart.sh入库→analyze.sh计算指标→alert.sh触发告警。任何一层故障不影响其他层运行,例如sqlite3写入失败,日志仍在rsyslog中保留,可人工恢复。
2.3 架构落地的关键权衡:为什么放弃Zabbix/Prometheus?
在设计初期,我也评估过将SMART数据接入Zabbix或Prometheus的方案。Zabbix有成熟的SMART监控模板,Prometheus可通过node_exporter的smartmoncollector获取指标。但深入评估后,我放弃了这两个方案,原因直指Ubuntu场景的核心矛盾:
Zabbix的侵入性太强:部署Zabbix Server需MySQL/PostgreSQL、Apache/Nginx、PHP,一个完整栈占用内存超500MB,对1GB RAM的树莓派或老旧笔记本(常见Ubuntu桌面用户)是沉重负担。更关键的是,Zabbix Agent在Ubuntu上默认不启用SMART采集,需手动修改
zabbix_agentd.conf并重启服务,而smartctl本身需要root权限,这导致权限模型复杂化——要么给Zabbix Agent加sudo能力(安全风险),要么用setuid二进制(违反Ubuntu安全基线)。Prometheus的运维成本过高:
node_exporter的smartmoncollector虽轻量,但它依赖smartctl的-j(JSON)输出格式,而该格式在Ubuntu 20.04默认源的smartmontools(v7.0)中不支持,需升级到v7.2+,这意味着要添加第三方PPA(如ppa:linuxuprising/smartmontools),破坏了Ubuntu LTS“稳定优先”的哲学。此外,Prometheus的alert.rules编写对新手不友好,一个expr: smartmon_device_info{job="node"} == 0的误配,可能导致所有硬盘告警失效。
最终选择纯cron+rsyslog+sqlite3方案,是因为它完美契合Ubuntu的“KISS原则”(Keep It Simple, Stupid):所有组件都是Ubuntu官方仓库默认安装或一键apt install即可,配置文件全在/etc/下,日志路径遵循/var/log/标准,备份只需cp /var/log/smart.log /var/lib/smart.db /backup/。一位刚学会sudo apt update的用户,按本文步骤操作,30分钟内就能拥有自己的硬盘健康数据中心。这比教会他配置Zabbix的item和trigger,要实在得多。
3. 核心细节解析:smartctl命令的21个关键参数与实战陷阱
3.1 设备识别:/dev/sdX、/dev/nvme0n1、/dev/sgX的抉择逻辑
在Ubuntu下执行smartctl前,第一步永远是精准识别目标设备。看似简单的lsblk或fdisk -l,实则暗藏玄机。我整理了三种设备路径的适用场景与风险:
/dev/sdX(如/dev/sda):这是最常见的SATA/SAS硬盘路径,由Linux内核的sd驱动管理。优势是smartctl对其支持最完善,几乎所有参数(包括-t long自检)都可用。陷阱在于:当系统挂载了USB移动硬盘或外接SSD时,/dev/sdX编号可能动态变化。例如,启动时USB硬盘是/dev/sdb,拔插后可能变成/dev/sdc,若你的监控脚本硬编码/dev/sdb,就会采集到错误设备。解决方案是使用/dev/disk/by-id/下的持久化链接,如/dev/disk/by-id/ata-WDC_WD10SPZX-22Z10T0_JD123456789-part1,它基于硬盘序列号生成,永不改变。/dev/nvme0n1:NVMe SSD的标准路径,由nvme驱动管理。优势是原生支持PCIe高速传输,smartctl -x -a /dev/nvme0n1能读取nvme专属属性(如Temperature、Available_Spare)。陷阱在于:部分老主板(如Intel 100系列芯片组)的NVMe驱动存在bug,smartctl -a可能返回Read NVMe Identify Controller failed: Operation not supported。此时需升级内核(Ubuntu 22.04默认5.15内核已修复多数问题)或改用/dev/sgX路径。/dev/sgX(如/dev/sg0):SCSI通用设备路径,通过sg3_utils包提供。优势是绕过具体驱动,直接与硬盘固件通信,对RAID卡(如LSI MegaRAID)后端的物理盘、USB-SATA桥接芯片(如JMicron JMS578)有奇效。例如,一块通过USB硬盘盒连接的西数红盘,在/dev/sdX下smartctl -a返回Device does not support SMART,但smartctl -d sat -a /dev/sg2(-d sat指定SAT层)却能成功读取。陷阱是/dev/sgX编号同样动态,且需额外安装sg3-utils,-d参数必须精确匹配桥接芯片类型(sat、usbjmicron、usbbcm等),试错成本高。
注意:永远不要对
/dev/sdX1(分区)运行smartctl!SMART是硬盘级协议,作用于整个物理设备。对分区操作会返回Inappropriate ioctl for device错误,并可能干扰分区表读取。
3.2smartctl核心参数详解:从入门到避坑
smartctl有数十个参数,但日常运维中高频使用的仅21个。我按使用频率和风险等级排序,并标注每个参数的“灵魂用途”与“血泪教训”:
-a(all):最常用,输出全部SMART信息。灵魂用途:首次全面摸底硬盘状态。教训:在高负载服务器上频繁执行-a会引发短暂IO阻塞,因它需读取固件多个ROM区域。建议在低峰期(如凌晨2点)执行。-H(health):健康摘要。灵魂用途:快速确认是否立即更换硬盘。教训:如前所述,它不可靠,仅作初步筛查,绝不能作为唯一依据。-i(info):基本信息。灵魂用途:确认硬盘型号、序列号、固件版本、总容量。教训:-i不读取SMART属性,速度极快,适合在脚本中先验证设备是否存在,再决定是否执行耗时的-a。-c(capabilities):自检能力。灵魂用途:查看硬盘支持哪些自检类型(short、long、conveyance)及预计耗时。教训:-c输出中的Offline data collection status若为"Offline data collection activity was suspended",说明上次自检被中断,需先执行sudo smartctl -o on /dev/sda启用离线收集。-t(test):启动自检。灵魂用途:主动触发硬盘自检。教训:-t short约2分钟,-t long可达数小时(1TB硬盘约4小时),期间硬盘响应变慢,dd if=/dev/zero of=/tmp/test bs=1M count=1000测速会下降30%。务必避开业务高峰。-C(captured):捕获自检日志。灵魂用途:-t启动后,用-C读取自检过程中的实时日志,观察进度。教训:-C需在自检进行中执行,结束后日志即被覆盖,错过就无法回溯。-l(log):读取日志页。灵魂用途:-l selftest查自检历史,-l error查错误日志(比dmesg更详细)。教训:-l error输出的Error 1 occurred at disk power-on lifetime: 12345 hours,这个12345是硬盘通电总时长,不是错误发生时间戳,需结合-i的Power_On_Hours换算实际日期。-x(extended):扩展信息。灵魂用途:对NVMe SSD,-x是必须的,否则-a不显示nvme专属属性。教训:在SATA硬盘上加-x无害,但会多输出几行无关信息,可忽略。-d(device type):指定设备类型。灵魂用途:解决USB/RAID设备识别问题。教训:-d sat适用于大多数USB-SATA桥接,但对USB-NVMe(如雷电SSD),需-d nvme,而非-d sat,否则报错。-s(settings):启用/禁用SMART。灵魂用途:-s on开启SMART(某些旧硬盘出厂关闭),-s off禁用(极少数场景需降低开销)。教训:-s off后,所有smartctl命令失效,需重启或-s on恢复,切勿在生产环境随意执行。-o(offline):启用/禁用离线收集。灵魂用途:-o on让硬盘在空闲时自动收集SMART数据,提升-a输出的实时性。教训:-o off会导致-a中Offline_Uncorrect等属性始终为0,误判为无错误。-f(format):输出格式。灵魂用途:-f brief精简输出,-f hex看原始十六进制值(调试固件用)。教训:-f vendor显示厂商私有解释,但多数情况下为空,因厂商不公开解码规则。-n(nocheck):节能模式下不唤醒。灵魂用途:-n standby在硬盘休眠时跳过检测,避免唤醒影响节能。教训:-n never强制唤醒,可能缩短硬盘寿命,仅在紧急诊断时用。-q(quiet):静默模式。灵魂用途:-q errorsonly只输出错误,适合脚本中if smartctl -q errorsonly -H /dev/sda; then ...判断。教训:-q noserial会隐藏序列号,影响by-id路径生成,慎用。-T(tolerance):容错级别。灵魂用途:-T permissive容忍部分SMART读取失败,继续输出其他属性。教训:-T verypermissive可能输出乱码,仅在固件严重损坏时尝试。-r(report):报告级别。灵魂用途:-r ioctl,2输出底层IOCTL调用详情,用于调试smartctl自身问题。教训:普通用户完全不需要,输出信息过于底层,徒增困惑。-B(backup):备份SMART数据。灵魂用途:-B /path/to/backup.bin将SMART ROM备份到文件,供固件工程师分析。教训:备份文件达数MB,且需root权限,日常运维无意义。-P(presets):加载预设。灵魂用途:-P show显示当前设备的预设参数(如-d sat的默认超时)。教训:预设由smartmontools内置,用户无法修改,仅作参考。-R(reset):重置属性。灵魂用途:-R 5重置ID#5(重映射扇区)的WORST值为当前VALUE,用于测试目的。教训:-R会永久修改硬盘固件中的WORST值,绝对禁止在生产硬盘上执行!这是smartctl最危险的参数。-S(save):保存属性。灵魂用途:-S on开启自动保存(现代硬盘默认开启)。教训:-S off禁用后,VALUE变化不会写入固件,下次重启还原,导致监控数据失真。--scan:扫描设备。灵魂用途:smartctl --scan自动列出所有可监控设备,是编写通用脚本的起点。教训:--scan不检查设备是否支持SMART,需配合-i二次验证。
3.3 实战案例:一块“健康”硬盘的深度解剖
让我们以一块真实的西数蓝盘(WD10SPZX,固件82.00A82)为例,演示如何用上述参数穿透PASSED表象:
# 步骤1:确认设备与基本信息 $ sudo smartctl -i /dev/sda === START OF INFORMATION SECTION === Model Family: Western Digital Blue Device Model: WDC WD10SPZX-22Z10T0 Serial Number: WD-WCC7K0XXXXXX Firmware Version: 82.00A82 User Capacity: 1,000,204,886,016 bytes [1.00 TB] Sector Sizes: 512 bytes logical, 4096 bytes physical Rotation Rate: 5400 rpm Device is: Not in smartctl database [for details use: -P showall] ATA Version is: ACS-3 T13/2161-D revision 5 SATA Version is: SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s) Local Time is: Mon Oct 23 10:15:22 2023 CST SMART support is: Available - device has SMART capability. SMART support is: Enabled # 关键!SMART已启用# 步骤2:查看自检能力(发现隐患) $ sudo smartctl -c /dev/sda === START OF READ SMART DATA SECTION === General SMART Values: Offline data collection status: (0x82) Offline data collection activity was completed without error. Auto Offline Data Collection: Enabled Self-test execution status: ( 24) The self-test routine was aborted by the host. Total time to complete Offline data collection: (12600) seconds. ... SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Short offline Completed without error 00% 12345 - # 2 Extended offline Aborted by host 90% 12340 -注意Self-test execution status显示Aborted by host,且LifeTime为12340小时,而-i中Power_On_Hours是12345小时——这意味着5小时前自检被强制中断,硬盘可能处于不稳定状态。
# 步骤3:读取错误日志(找到根源) $ sudo smartctl -l error /dev/sda === START OF READ ERROR LOG SECTION === Error 1 occurred at disk power-on lifetime: 12340 hours (514 days + 4 hours) When the command that caused the error occurred, the device was active or idle. After command completion, registers were: ER ST SC SN CL CH DH -- -- -- -- -- -- -- 40 51 01 00 00 00 e0 Error: UNC at LBA = 0x00000000 = 0 Commands leading to the command that caused the error were: CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name -- -- -- -- -- -- -- -- ---------------- -------------------- c8 00 08 00 00 00 e0 08 00:00:00.000 READ DMA c8 00 08 00 00 00 e0 08 00:00:00.000 READ DMA c8 00 08 00 00 00 e0 08 00:00:00.000 READ DMAUNC(Uncorrectable Error)错误,LBA为0,指向硬盘最开始的扇区——这通常是主引导记录(MBR)或GPT头所在位置。结合自检中断,基本可断定是电源不稳或线缆接触不良导致的读取失败,而非硬盘物理损坏。
# 步骤4:检查关键属性趋势(确认恶化) $ sudo smartctl -a /dev/sda | grep -E "(Reallocated_Sector_Ct|Current_Pending_Sector|UDMA_CRC_Error_Count)" 5 Reallocated_Sector_Ct 0x0033 200 200 144 Pre-fail Always - 0 197 Current_Pending_Sector 0x0032 200 200 0 Old_age Always - 0 198 Offline_Uncorrect 0x0030 100 253 0 Old_age Offline - 0 199 UDMA_CRC_Error_Count 0x0032 200 200 0 Old_age Always - 12表面看全为0,但UDMA_CRC_Error_Count为12,且-c显示自检中断,说明CRC错误已积累。此时应立即检查SATA线缆和主板接口,而非等待Reallocated_Sector_Ct增长。
实操心得:我养成了一个习惯——每次系统更新内核或更换硬件后,必跑一遍
smartctl -c /dev/sdX。因为新内核的AHCI驱动或新主板的SATA控制器,可能与旧硬盘固件存在兼容性问题,Aborted by host就是最直接的警示灯。早发现,早换线缆,比等硬盘报废再抢救数据,成本低百倍。
4. 实操过程:从零搭建Ubuntu硬盘健康监控系统
4.1 环境准备与基础工具安装
在Ubuntu 20.04/22.04/24.04上,所有必需工具均可通过apt一键安装,无需添加任何PPA。执行以下命令:
# 更新包索引并安装核心工具 sudo apt update && sudo apt install -y smartmontools sqlite3 rsyslog gnuplot-core # 验证安装 smartctl -V # 应输出 smartmontools 7.x 版本 sqlite3 --version # 应输出 3.x 版本smartmontools包已包含smartctl和smartd,rsyslog是Ubuntu默认日志系统,gnuplot-core提供命令行绘图能力(无GUI依赖)。注意:gnuplot-x11(带图形界面)非必需,gnuplot-core已足够生成PNG趋势图。
提示:如果系统已安装
rsyslog但配置被修改,可先重置为默认:sudo cp /usr/share/rsyslog/rsyslog.conf /etc/rsyslog.conf && sudo systemctl restart rsyslog。
4.2 创建SMART日志专用目录与数据库
为保持系统整洁,所有SMART相关文件集中存放在/var/lib/smartmon/:
# 创建目录并设置权限 sudo mkdir -p /var/lib/smartmon/{logs,db,scripts} sudo chown root:root /var/lib/smartmon sudo chmod 755 /var/lib/smartmon # 初始化SQLite数据库 sudo sqlite3 /var/lib/smartmon/db/history.db << 'EOF' CREATE TABLE IF NOT EXISTS smart_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, device TEXT NOT NULL, attr_id INTEGER NOT NULL, name TEXT NOT NULL, flag TEXT, value INTEGER, worst INTEGER, thresh INTEGER, type TEXT, updated TEXT, raw_value TEXT, raw_bytes BLOB ); CREATE INDEX IF NOT EXISTS idx_device_name ON smart_history(device, name); CREATE INDEX IF NOT EXISTS idx_timestamp ON smart_history(timestamp); EOF数据库设计遵循“宽表”原则,raw_bytes字段预留为BLOB,以便未来存储完整的smartctl -x -a二进制输出(-x参数可输出原始字节流)。索引idx_device_name加速按设备和属性查询,idx_timestamp加速时间范围筛选。
4.3 配置rsyslog接收SMART日志
编辑/etc/rsyslog.d/50-smart.conf,创建专用日志通道:
# /etc/rsyslog.d/50-smart.conf # 定义SMART日志模板 template(name="SmartLog" type="string" string="%timestamp:::date-rfc3339% %hostname% SMART[%procid%]: %msg%\n") # 将所有以"SMART["开头的日志写入专用文件 if $programname == 'SMART' then { action(type="omfile" file="/var/lib/smartmon/logs/smart.log" template="SmartLog") stop } # 允许外部程序(如smartd)通过logger发送日志 module(load="imuxsock" SysSock.Use="off") input(type="imuxsock" Socket="/dev/log" CreatePath="on")然后重启rsyslog:
sudo systemctl restart rsyslog此配置确保所有logger -t SMART "message"日志被精准捕获,且时间戳格式为RFC3339(2023-10-23T10:15:22+08:00),便于后续awk解析。
4.4 编写SMART数据采集与解析脚本
创建采集脚本/var/lib/smartmon/scripts/collect.sh:
#!/bin/bash # /var/lib/smartmon/scripts/collect.sh # 功能:遍历所有ATA/NVMe设备,执行smartctl采集,并注入rsyslog # 获取所有可监控设备(排除loop、ram、zram等虚拟设备) DEVICES=$(lsblk -d -o NAME,TYPE | awk '$2=="disk"{print "/dev/"$1}') for DEV in $DEVICES; do # 跳过NVMe设备,用单独逻辑处理(因参数不同) if [[ "$DEV" == "/dev/nvme"* ]]; then continue fi # 检查设备是否支持SMART if sudo smartctl -i "$DEV" 2>/dev/null | grep -q "SMART support is: Enabled"; then echo "Collecting SMART from $DEV..." # 执行完整采集,输出到rsyslog sudo smartctl -x -a "$DEV" 2>/dev/null | \ while IFS= read -r line; do logger -t SMART "DEVICE:$DEV;LINE:$line" done fi done # 单独处理NVMe设备 for NVME in /dev/nvme*; do if [[ -b "$NVME" ]]; then if sudo smartctl -i "$NVME" 2>/dev/null | grep -q "NVMe"; then echo "Collecting NVMe SMART from $NVME..." sudo smart