Megacli 批次磁碟巡檢

飞飞6779發表於2024-09-12

情況基本介紹

原理:根據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 臺!

相關文章