情况基本介绍
原理:根据megacli -ldpdinfo -aALL -Nolog命令输出的Count错误计数来判断磁盘预错误信息,以实现故障提前处置,避免磁盘连续非预期离线,导致存储集群服务故障。
背景:
现网生产环境,不允许安装额外的软件。
smartctl版本较老且不允许升级,部分smart参数不能识别。
python版本2.7和熟悉的python3差别也挺大,所以选择用shell编写脚本。
步骤:
定义输出目标文件,和结果计数对象。
从host文件里读取server列表,并遍历执行megacli命令。
对megacli的输出进行格式化和计数,并在屏幕中反馈故障信息。
环境要求:
脚本执行主机需要有免密登录目标主机的权限。
目标主机需要有megacli工具,如果有storcli,可以对脚本的计数、匹配语句稍作修改,且storcli功能更强。
目前脚本的不足,和下一步的改进方向:
目前未统计故障硬盘数量,后续可根据磁盘ID等信息统计故障数量并输出。
未对故障信息进行转存记录。
未联动告警功能。
megacli命令过滤后的原始输出:
Virtual Drive: 0 (Target Id: 0)
RAID Level : Primary-1, Secondary-0, RAID Level Qualifier-0
Size : 446.625 GB
State : Optimal
Enclosure Device ID: 8
Slot Number: 38
Device Id: 24
Media Error Count: 0
Other Error Count: 0
Predictive Failure Count: 0
Firmware state: Online, Spun Up
Drive Temperature :31C (87.80 F)
Enclosure Device ID: 8
Slot Number: 39
Device Id: 34
Media Error Count: 0
Other Error Count: 0
Predictive Failure Count: 0
Firmware state: Online, Spun Up
Drive Temperature :33C (91.40 F)
shell脚本内容:
#!/bin/bash
# 定义一个空数组failHost,用于存储执行失败的主机
failHost=()
# 判断当前目录下是否有名为“年月日-时分秒-OsdDiskCheck.csv”的文件,如果没有,就新建一个:
ResultFile="$(date +%Y%m%d-%H%M%S)-OsdDiskCheck.csv"
if [ ! -f "$ResultFile" ]; then
touch "$ResultFile"
else
echo "$ResultFile 巡检结果文件已存在,请检查是否需要删除!"
fi
# 读取主机列表文件内容到数组
mapfile -t hosts < "osdServerList.txt"
hostsLen="${#hosts[@]}"
hostsSuc=0
# 遍历数组中的每一行主机名
for line in "${hosts[@]}"; do
echo "----------ssh $line----------"
# 尝试在远端主机$line 上执行命令:
if ! diskOutPut=`ssh $line 'megacli -ldpdinfo -aALL -Nolog | egrep -i "Virtual Drive|RAID Level|^Size|^State|Enclosure Device|Slot Number|Device Id|media error|other error|^Predictive|Firmware stat|Temperature"' && sleep 5`
then
echo "$line 巡检失败,请检查"
failHost+=(" $line")
else
hostsSuc=$((hostsSuc+1))
# 1. 分割outPut对象,:做为分隔符,之前的字符定义为key,之后的字符为value
while IFS=: read -r key value; do
key=`echo $key | awk -F' ' '{print $1}'`
value="${value#"${value%%[![:space:]]*}"}"
# 对命令输出里的Count(错误计数)进行信息组合,加上raid ID和eid、sid
if [[ $key =~ "Virtual Drive" ]]; then
keyVirt="RaidID_`echo $value|awk '{print $1}'`"
elif [[ $key =~ "Enclosure Device ID" ]]; then
keyEID="E_$value"
elif [[ $key =~ "Slot Number" ]]; then
keySID="S_$value"
elif [[ $key =~ "Count" ]]; then
key="Host: $line, $keyVirt, $keyEID~$keySID, $key"
# 如果value不为0,就输出:“发现错误:$key---$value”
if [[ $value != 0 ]]; then
echo "发现磁盘错误:$key---$value"
if [[ $key =~ "Firmware state" ]] && [[ $value =~ "Online" ]]; then
echo "该告警磁盘仍然在线,请密切关注,确认是否手动踢盘!"
else
echo "该告警磁盘已处于故障状态!"
fi
fi
else
key="$key"
fi
echo "$key---$value" >> "$ResultFile"
done <<<"$diskOutPut"
fi
done
# 判断failHost数组是否为空,如果为空,就打印“所有主机巡检执行成功”,否则打印出“执行失败的主机:${failHost[@]}”:
echo "主机列表共 $hostsLen 台主机,巡检执行成功 $hostsSuc 台!"
if [ ${#failHost[@]} -ne 0 ]; then
echo "执行失败的主机有:${failHost[@]}。"
fi
执行输出:
……
----------ssh z***3----------
Warning: Permanently added 'z***3' (ECDSA) to the list of known hosts.
发现磁盘错误:Host: z***3, RaidID_1, E_8~S_0, Other Error Count---6
该告警磁盘已处于故障状态!
发现磁盘错误:Host: z***3, RaidID_6, E_8~S_5, Other Error Count---3
该告警磁盘已处于故障状态!
发现磁盘错误:Host: z***3, RaidID_9, E_8~S_8, Other Error Count---7
该告警磁盘已处于故障状态!
----------ssh z***4----------
Warning: Permanently added 'z***4' (ECDSA) to the list of known hosts.
----------ssh z***7----------
Warning: Permanently added 'z***7' (ECDSA) to the list of known hosts.
发现磁盘错误:Host: z***7, RaidID_2, E_8~S_2, Media Error Count---20
该告警磁盘已处于故障状态!
主机列表共 15 台主机,巡检执行成功 15 台!
标签:Count,巡检,Megacli,value,echo,key,Error,磁盘
From: https://www.cnblogs.com/feifei6779/p/18409597