系统报IO告警,在带外无异常的情况下,在操作系统中进行排障 故障现象 监测平台报障IO占用率和延迟过高
初步排障 登录带外观察是否有故障日志,无论是否有故障日志,均需要进一步进行二次核对
JBOD直通无RAID排障
使用smartctl命令观察磁盘健康状态,网络上有大量教程,不再赘述
如果磁盘本身无故障,观察输出结果中的199 UltraDMA CRC Error Count这一行是否有记录,这是硬件通信错误的日志,如果有记录到纠正次数,那就说明发生了硬件连接的问题,如硬盘背板故障,连接线故障,接口松动等
批量排障命令参考
for i in {a..z}; do [ -b "/dev/sd$i" ] && echo "sd$i:" && sudo smartctl -a "/dev/sd$i" | grep "199"; done
RAID阵列模式排障 做了阵列的磁盘无法直接使用smartctl进行排障,需要改为smartctl -a -d megaraid,3 /dev/sdX的方式排障,megaraid,后面跟你的硬盘的编号,/dev/sdX则是对应这个阵列在系统中的编号
范例:
1 2 3 4 5 6 7 8 # raid5阵列,挂载为/dev/sdb # 阵列中disk2存在故障 smartctl -a -d megaraid,2 /dev/sdb # 批量查询所有阵列所有盘 # 其中a..d是用于遍历/dev/sda-d,根据你的阵列情况调整 # 其中0..10是用于遍历一个阵列下有多少个硬盘,根据你的阵列情况调整 for raid in {a..d};do for disk in {0..10};do smartctl -a -d megaraid,$disk /dev/sd$raid | grep -i "CRC\|Error";done;done
HDD SSD二合一版
该脚本会在当前目录输出smartctl的日志源码到disk_error_$(date +%Y%m%d_%H%M%S).log文件
推荐使用此单行模式,复制粘贴直接用,不需要创建shell文件
1 log_file="disk_error_$(date +%Y%m%d_%H%M%S).log"; for raid in {a..d}; do [ -b "/dev/sd$raid" ] && for disk in {0..23}; do smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1 && output=$(smartctl -a -d megaraid,$disk /dev/sd$raid) && serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}') && if echo "$output" | grep -q "SSD"; then reallocated_sectors=$(echo "$output" | grep "Reallocated_Sector_Ct" | awk '{print $10}'); reallocated_sectors=${reallocated_sectors:-0}; current_pending=$(echo "$output" | grep "Current_Pending_Sector" | awk '{print $10}'); current_pending=${current_pending:-0}; reported_uncorrect=$(echo "$output" | grep "Reported_Uncorrect" | awk '{print $10}'); reported_uncorrect=${reported_uncorrect:-0}; offline_uncorrect=$(echo "$output" | grep "Offline_Uncorrectable" | awk '{print $10}'); offline_uncorrect=${offline_uncorrect:-0}; crc_errors=$(echo "$output" | grep "CRC_Error_Count" | awk '{print $10}'); crc_errors=${crc_errors:-0}; [ "$reallocated_sectors" -gt 0 ] || [ "$current_pending" -gt 0 ] || [ "$reported_uncorrect" -gt 0 ] || [ "$offline_uncorrect" -gt 0 ] || [ "$crc_errors" -gt 0 ] && echo "$output" >> "$log_file" && echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n\033[36;1m05 重分配扇区计数(Reallocated Sector Count):\033[31;1m$reallocated_sectors\033[0m\n\033[36;1m197 当前待处理扇区(Current Pending Sector Count):\033[31;1m$current_pending\033[0m\n\033[36;1m已报告的不可纠正错误(Reported Uncorrectable Errors):\033[31;1m$reported_uncorrect\033[0m\n\033[36;1m离线不可纠正错误(Offline Uncorrectable):\033[31;1m$offline_uncorrect\033[0m\n\033[36;1m接口CRC错误计数(CRC Error Count):\033[31;1m$crc_errors\033[0m\n"; else read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); read_uncorrected=${read_uncorrected:-0}; verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); verify_uncorrected=${verify_uncorrected:-0}; total_uncorrected=$(echo "$output" | grep "Total uncorrected errors" | awk '{print $NF}'); total_uncorrected=${total_uncorrected:-0}; grown_defect_list=$(echo "$output" | grep "Elements in grown defect list" | awk '{print $NF}'); grown_defect_list=${grown_defect_list:-0}; non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); non_medium=${non_medium:-0}; [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$total_uncorrected" -gt 0 ] || [ "$grown_defect_list" -gt 0 ] || [ "$non_medium" -gt 0 ] && echo "$output" >> "$log_file" && echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n\033[36;1m读无法纠正错误(Read total uncorrected errors):\033[31;1m$read_uncorrected\033[0m\n\033[36;1m校验无法纠正错误(Verify total uncorrected errors):\033[31;1m$verify_uncorrected\033[0m\n\033[36;1m总无法纠正错误(Total uncorrected errors):\033[31;1m$total_uncorrected\033[0m\n\033[36;1m已增长缺陷列表元素(Elements in grown defect list):\033[31;1m$grown_defect_list\033[0m\n\033[36;1m非介质错误(Non-medium error count):\033[31;1m$non_medium\033[0m\n"; fi; done; done
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 # !/bin/bash # 日志文件以日期时间命名 log_file="disk_error_$(date +%Y%m%d_%H%M%S).log" # 遍历可能的RAID设备(sda, sdb, sdc, sdd) for raid in {a..d}; do if [ -b "/dev/sd$raid" ]; then for disk in {0..23}; do if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then output=$(smartctl -a -d megaraid,$disk /dev/sd$raid) serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}') if echo "$output" | grep -q "SSD"; then # ================= SSD ================= reallocated_sectors=$(echo "$output" | grep "Reallocated_Sector_Ct" | awk '{print $10}') reallocated_sectors=${reallocated_sectors:-0} current_pending=$(echo "$output" | grep "Current_Pending_Sector" | awk '{print $10}') current_pending=${current_pending:-0} reported_uncorrect=$(echo "$output" | grep "Reported_Uncorrect" | awk '{print $10}') reported_uncorrect=${reported_uncorrect:-0} offline_uncorrect=$(echo "$output" | grep "Offline_Uncorrectable" | awk '{print $10}') offline_uncorrect=${offline_uncorrect:-0} crc_errors=$(echo "$output" | grep "CRC_Error_Count" | awk '{print $10}') crc_errors=${crc_errors:-0} if [ "$reallocated_sectors" -gt 0 ] || [ "$current_pending" -gt 0 ] || \ [ "$reported_uncorrect" -gt 0 ] || [ "$offline_uncorrect" -gt 0 ] || [ "$crc_errors" -gt 0 ]; then echo "$output" >> "$log_file" echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n" echo -e "\033[36;1m05 重分配扇区计数(Reallocated Sector Count):\033[31;1m$reallocated_sectors\033[0m" echo -e "\033[36;1m197 当前待处理扇区(Current Pending Sector Count):\033[31;1m$current_pending\033[0m" echo -e "\033[36;1m已报告的不可纠正错误(Reported Uncorrectable Errors):\033[31;1m$reported_uncorrect\033[0m" echo -e "\033[36;1m离线不可纠正错误(Offline Uncorrectable):\033[31;1m$offline_uncorrect\033[0m" echo -e "\033[36;1m接口CRC错误计数(CRC Error Count):\033[31;1m$crc_errors\033[0m\n" fi else # ================= HDD ================= read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}') read_uncorrected=${read_uncorrected:-0} verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}') verify_uncorrected=${verify_uncorrected:-0} total_uncorrected=$(echo "$output" | grep "Total uncorrected errors" | awk '{print $NF}') total_uncorrected=${total_uncorrected:-0} grown_defect_list=$(echo "$output" | grep "Elements in grown defect list" | awk '{print $NF}') grown_defect_list=${grown_defect_list:-0} non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}') non_medium=${non_medium:-0} if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || \ [ "$total_uncorrected" -gt 0 ] || [ "$grown_defect_list" -gt 0 ] || [ "$non_medium" -gt 0 ]; then echo "$output" >> "$log_file" echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n" echo -e "\033[36;1m读无法纠正错误(Read total uncorrected errors):\033[31;1m$read_uncorrected\033[0m" echo -e "\033[36;1m校验无法纠正错误(Verify total uncorrected errors):\033[31;1m$verify_uncorrected\033[0m" echo -e "\033[36;1m总无法纠正错误(Total uncorrected errors):\033[31;1m$total_uncorrected\033[0m" echo -e "\033[36;1m已增长缺陷列表元素(Elements in grown defect list):\033[31;1m$grown_defect_list\033[0m" echo -e "\033[36;1m非介质错误(Non-medium error count):\033[31;1m$non_medium\033[0m\n" fi fi fi done fi done
输出效果如下
以下部分的忽略掉即可,老版本的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # 批量巡检脚本 - 适用于HDD # 遍历可能的RAID设备(sda, sdb, sdc, sdd) for raid in {a..d}; do # 检查设备是否存在 if [ -b "/dev/sd$raid" ]; then # 遍历每个RAID设备上的物理磁盘(0到23号) for disk in {0..23}; do # 检查磁盘是否可访问(尝试获取基本信息,输出重定向到/dev/null) if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then # 获取完整的SMART数据 output=$(smartctl -a -d megaraid,$disk /dev/sd$raid) # 从输出中提取序列号 serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}') # 提取读取无法纠正错误次数(最后一列) read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}') # 提取验证无法纠正错误次数(最后一列) verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}') # 提取非介质错误次数(最后一列) non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}') # 检查是否有任何错误(任一错误计数大于0) if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then # 将有错误的磁盘完整SMART数据追加到日志文件 echo "$output" >> disk_error.log # 输出格式化错误信息 echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n" echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m" echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m" echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m" echo -e "\n" fi fi done fi done # 整合为一行,一条龙服务 for raid in {a..d}; do if [ -b "/dev/sd$raid" ]; then for disk in {0..23}; do if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then output=$(smartctl -a -d megaraid,$disk /dev/sd$raid); serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}'); read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then echo "$output" >> disk_error.log; echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"; echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m"; echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m"; echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m"; echo -e "\n"; fi; fi; done; fi; done
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 # 批量巡检脚本 - 适用于SSD # 遍历可能的RAID设备(sda, sdb, sdc, sdd) for raid in {a..d}; do # 检查设备是否存在 if [ -b "/dev/sd$raid" ]; then # 遍历每个RAID设备上的物理磁盘(0到23号) for disk in {0..23}; do # 检查磁盘是否可访问(尝试获取基本信息,输出重定向到/dev/null) if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then # 获取完整的SMART数据 output=$(smartctl -a -d megaraid,$disk /dev/sd$raid) # 从输出中提取序列号 serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}') # 检测磁盘类型(SSD或HDD) if echo "$output" | grep -q "SSD"; then # SSD磁盘:使用Media_and_Data_Integrity_Errors等属性 media_errors=$(echo "$output" | grep "Media_and_Data_Integrity_Errors" | awk '{print $10}') media_errors=${media_errors:-0} # 对于SSD,我们主要关注媒体错误和ECC错误 uncorrected_errors=$(echo "$output" | grep "Error_Information_Log_Entries" | awk '{print $10}') uncorrected_errors=${uncorrected_errors:-0} # 检查SSD错误 if [ "$media_errors" -gt 0 ] || [ "$uncorrected_errors" -gt 0 ]; then echo "$output" >> disk_error.log echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n" echo -e "\033[36;1m媒体和数据完整性错误:\033[31;1m$media_errors\033[36;1m" echo -e "\033[36;1m错误信息日志条目:\033[31;1m$uncorrected_errors\033[36;1m" echo -e "\n" fi else # HDD磁盘:使用原有的错误计数器 read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}') read_uncorrected=${read_uncorrected:-0} verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}') verify_uncorrected=${verify_uncorrected:-0} non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}') non_medium=${non_medium:-0} # 检查HDD错误 if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then echo "$output" >> disk_error.log echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n" echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m" echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m" echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m" echo -e "\n" fi fi fi done fi done # 一条龙服务 for raid in {a..d}; do if [ -b "/dev/sd$raid" ]; then for disk in {0..23}; do if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then output=$(smartctl -a -d megaraid,$disk /dev/sd$raid); serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}'); if echo "$output" | grep -q "SSD"; then media_errors=$(echo "$output" | grep "Media_and_Data_Integrity_Errors" | awk '{print $10}'); media_errors=${media_errors:-0}; uncorrected_errors=$(echo "$output" | grep "Error_Information_Log_Entries" | awk '{print $10}'); uncorrected_errors=${uncorrected_errors:-0}; if [ "$media_errors" -gt 0 ] || [ "$uncorrected_errors" -gt 0 ]; then echo "$output" >> disk_error.log; echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"; echo -e "\033[36;1m媒体和数据完整性错误:\033[31;1m$media_errors\033[36;1m"; echo -e "\033[36;1m错误信息日志条目:\033[31;1m$uncorrected_errors\033[36;1m"; echo -e "\n"; fi; else read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); read_uncorrected=${read_uncorrected:-0}; verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); verify_uncorrected=${verify_uncorrected:-0}; non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); non_medium=${non_medium:-0}; if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then echo "$output" >> disk_error.log; echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"; echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m"; echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m"; echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m"; echo -e "\n"; fi; fi; fi; done; fi; done
以上部分的忽略掉即可,老版本的
原始错误日志解读 HDD范例 范例:
报错内容
翻译
说明
Error Corrected by ECC
ECC纠错
当某个扇区存在错误时,硬盘通过内置的错误校正码(ECC)机制自动完成的纠错次数。
Total errors corrected
已纠错总次数
记录累计成功纠正的错误总数(包含所有纠错方式)。
Correction algorithm invocations
纠错算法调用次数
硬盘调用纠错算法的次数,部分可能无需实际改写即可修复;一般无需重点关注。
Gigabytes processed
已处理数据量(GB)
表示在统计期间,通过 ECC 机制处理过的数据总量(以 GB 计)。
Total uncorrected errors
未能纠错总数
ECC 无法修复的错误次数,表示确实发生了数据损坏;若大于 0,需立即关注。
Non-medium error count
非介质错误计数
非存储介质本身的故障,例如接口、背板、线缆、电源等导致的通信或传输错误。
fast rereads
快速重读
通过快速重读实现的自动纠错,对性能影响较小。
delayed rereads
延迟重读
通过延迟重读实现的纠错,通常会增加 I/O 响应时间。
rewrites
重写
当重读成功后,将正确的数据重新写回故障扇区,以防止未来再次出错。
范例中ECC纠错2555次,且存在4次无法纠错,且非介质故障高达13次,该硬盘急需维护。
SSD范例
报错内容
翻译
说明
Reallocated Sector Count
重分配扇区计数
表示硬盘将坏掉或不可靠的扇区重映射到备用扇区的次数。数值大于 0 意味着盘体已经出现物理坏块。若持续增加,说明硬盘劣化严重,应尽快备份并考虑更换。
Reported Uncorrectable Errors
报告无法纠正错误
硬盘在正常读写中发生的、ECC 无法修复的错误次数。这类错误会导致数据直接损坏,是严重的健康警告指标。
Current Pending Sector Count
当前待处理扇区
等待进一步确认或重新分配的扇区数量。通常表示这些扇区在读写中出现问题,待后续重写确认是否稳定。若数值不降反升,说明盘体状态持续恶化。
Offline Uncorrectable
离线不可校正错误
硬盘在离线检测或自检时发现的无法修复错误。表示硬盘在后台扫描时检测到了坏块,可靠性降低。
CRC Error Count
接口 CRC 错误次数
表示主机与硬盘之间数据传输时出现的循环冗余校验错误,通常由线缆、接口、背板、电磁干扰或电源问题引起,而非硬盘介质损坏。