centos7之zabbix使用Megacli监控磁盘整列中的硬盘状态

参考地址:https://www.chenghuajie.cn/906.html

 首先,监控硬盘状态分为几种情况:

  1、如果zabbix官方提供监控模板,直接导入应用就行,像我前面写过的dell R720等服务器。

       2、参考地址里面写的主要监控方式是分区,这样的如果我一个磁盘阵列12块硬盘,这些硬盘就划了一个分区,这样监控没有意义。真的就是死就死了,只不过死了以后你能第一时间知道罢了。

       3、也是我下面要说的这种情况,我不监控分区。使用场景是如果磁盘整列做了RAID5,死一块硬盘,及时替换上去新的硬盘,这样就没有问题了。最多也是等他重新给新硬盘同步一份数据,并不影响使用,真正能做到故障第一之间发现。

硬件需求:

  1、python 2.6.6

       2、CentOS release 6.5

       3、服务器型号DELL T410

       4、因为使用的是zabbix_agentd配置文件,所以这个台服务器必须是安装了zabbix_agentd。

       5、zabbix3.2.6

一、MegaCli工具 

  1、安装就不在这里阐述了,网上一搜一大堆。

  Slot Number: 11 #硬盘编号,一个组是从0开始计算,依次类推。
  Media Error Count: 0 #坏道,如果硬盘出现问题,这个值就不会等于0
  Other Error Count: 0 #硬盘松动,越需要注意
  Firmware state: Online, Spun Up #在线状态

  2、安装方式:

  打开https://www.broadcom.com/support/download-search,在这里面搜索MegaCli

        

     

       

     

  下载下来以后copy到系统脸里面直接rpm -ivh安装即可。

   命令位置在 /opt/MegaRAID/MegaCli/MegaCli64

#/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -Lall -aALL  #查看raid级别

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -aALL #查看raid卡信息

#/opt/MegaRAID/MegaCli/MegaCli64 -PDList -aALL #查看硬盘信息

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpBbuCmd -aAll #查看电池信息

#/opt/MegaRAID/MegaCli/MegaCli64 -FwTermLog -Dsply -aALL #查看raid卡日志

#/opt/MegaRAID/MegaCli/MegaCli64 -adpCount #显示适配器个数

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpGetTime –aALL #显示适配器时间

#/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -LALL -aAll  #显示所有逻辑磁盘组信息

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpBbuCmd -GetBbuStatus -aALL |grep 'Charger Status' #查看电池充电状态

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpBbuCmd -GetBbuStatus -aALL #显示BBU状态信息

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpBbuCmd -GetBbuCapacityInfo -aALL #显示BBU容量信息

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpBbuCmd -GetBbuDesignInfo -aALL #显示BBU设计参数

#/opt/MegaRAID/MegaCli/MegaCli64 -AdpBbuCmd -GetBbuProperties -aALL #显示当前BBU属性

#/opt/MegaRAID/MegaCli/MegaCli64 -cfgdsply -aALL #显示raid卡型号,raid设置,disk相关信息
其他命令

    3、查看所有硬盘信息及状态,参数很详细。

megacli -PDList -aALL

  4、使用下面命令抓取我们需要的信息,这里提示因为Other Error Count我这里在监控的时候是抓取的,但是监控的时候没有选择这项,主要原因是线上有用的硬盘报这样的错,但是不影响使用,就偷个懒。

megacli -PDList -aALL |egrep  "Slot Number|Media Error Count|Other Error Count|Firmware state”

  5、zabbix_agentd安装方式

  https://www.cnblogs.com/lei0213/p/8858269.html

二、编写脚本

  1、自动发现脚本,自动查询机器上有多少块硬盘。这里需要注意一项zabbix接收的json数据,注意输出的结果,如下:

  数据结果案例:

{
        "data":[
                {"{#DISK_NAME}":"sda"},
                {"{#DISK_NAME}":"sdb"},
                {"{#DISK_NAME}":"sdc"}
        ]
}

  输出以后记得检测一下,是不是合法的json数据,https://www.json.cn/

  

  下面当有硬盘真的被拔出来以后,就彻底没有了,所以你检测时候它会返回一个空,这就尴尬了。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os

data_all = []
info_dict = {}
data = {}
data_list= []
def disk_list_info():
    info_all = os.popen('sudo megacli -PDList -aALL |egrep  "Slot Number|Media Error Count|Firmware state"')
    for i in info_all:
        data_all.append(i.strip())
    solt_num = 0
    for i in data_all:
        info=i.strip("\n")
        name=info.split(":")[0]
        value=info.split(":")[1]
        if name == "Slot Number":
            solt_num += 1
            info_dict["Slot Number"] = json.dumps(solt_num)
        elif name == "Media Error Count":
            info_dict["Media Error Count"]  = value
        elif  name == "Other Error Count":
            info_dict["Other Error Count"] = value
        elif  name == "Firmware state":
            info_dict["Firmware state"] = value
            disk_info_format(info_dict)
        else:
            pass

def disk_info_format(args):
    global data
    disk_name = {}
    if args["Slot Number"]:
        disk_name["{#DISK_NAME}"] = args["Slot Number"]
        data_list.append(disk_name)

if __name__ == '__main__':
    disk_list_info()
    os.popen('sudo rm -rf /etc/zabbix/scripts/test/MegaSAS.log')
    data["data"] = data_list
    jsonStr = json.dumps(data)
    print(jsonStr)
disk-diskcovery.py

  下面是最终版,这里面要注意两点:1、你的MegaCli的执行命令在什么位置,需要更改。2、每次执行完命令以后,会生成一个MegaSAS.log,必须要删除,它是以a+的方式增加的,不清理会变的异常庞大。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os

data_all = []
info_dict = {}
data = {}
data_list= []

def disk_list_info():
    info_all = os.popen('sudo megacli  -PDList -aALL -Nolog |egrep  "Media Error Count|SAS Address|Firmware state"')
    for h in info_all:
        data_all.append(h.strip())
    for i in data_all:
        info = i.strip('\n')
        name=info.split(":")[0]
        value=info.split(":")[1]
        if name == "Media Error Count":
            info_dict["Media Error Count"] = value
        elif  name == "Firmware state":
            info_dict["Firmware state"] = value
        elif name == "SAS Address(0)":
            info_dict["SAS Address(0)"] = value
            disk_info_format(info_dict)
        else:
            pass


def disk_info_format(args):
    global data
    disk_name = {}
    if args["SAS Address(0)"]:
        disk_name["{#DISK_NAME}"] = args["SAS Address(0)"]
        data_list.append(disk_name)
    else:
        pass

if __name__ == '__main__':
    disk_list_info()
    data["data"] = data_list
    jsonStr = json.dumps(data)
    print(jsonStr)
disk-discovery.py 最终版

 

 

  2、监控脚本

  脚本解释,如果硬盘信息是Media Error Count不等于0,Predictive Failure Count不等于0,Firmware state: Online, Spun Up 不是在线状态,就输出1,否则输出0。当然你也改改,如果0提醒硬盘有坏道,如果1提醒硬盘不在线,如果输出3硬盘状态良好等等。

  注意,在执行megacli命令的时候,在脚本当前目录会生成一个MegaSAS.log文件,在执行完命令以后需要删除该文件,这里需要注意,需要加上绝对路劲,os.path.join()不行,python2.7

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import time

arg = sys.argv[1]

data_all = []
info_dict = {}
data = []
data_format = {}
def disk_list_info():
    info_all = os.popen('sudo megacli -PDList -aALL |egrep  "Slot Number|Media Error Count|Firmware state"')
    for i in info_all:
        data_all.append(i.strip())
    solt_num = 0
    for i in data_all:
        info = i.strip("\n")
        name = info.split(":")[0]
        value = info.split(":")[1]
        if name == "Slot Number":
            solt_num += 1
            info_dict["Slot Number"] = solt_num
        elif name == "Media Error Count":
            info_dict["Media Error Count"] = value
        elif name == "Other Error Count":
            info_dict["Other Error Count"] = value
        elif name == "Firmware state":
            info_dict["Firmware state"] = value
            disk_info_format(info_dict)
        else:
            pass
def disk_info_format(args):
    global data_format
    if args["Slot Number"]:
        val = {'Slot Number {0}'.format(args["Slot Number"]):{'Media Error Count':args['Media Error Count'],'Firmware state':args['Firmware state']}}
        data_format.update(val)

if __name__ == '__main__':
    disk_list_info()
    os.popen('sudo rm -rf /etc/zabbix/scripts/test/MegaSAS.log')
    for i in data_format:
        keva = 'Slot Number '+''+ i[12::] +''
        if arg == i[12::]:
            if data_format[keva]['Media Error Count'].strip() == "0" and data_format[keva]['Firmware state'].strip() == "Online, Spun Up":
                print("0")
            else:
                print("1")
        else:
            pass
disk-health.py

   终极版,我们以SAS Address唯一值去判断,这个硬盘在不在,然后再判断他Media Error Count等不等于0,Firmware state: Online, Spun Up 是不是在线状态。最终版的自动发现也是这么一个逻辑。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os


arg = sys.argv[1]

data_all = []
info_dict = {}
data = []
data_format = {}
def disk_list_info():
    info_all = os.popen('sudo megacli  -PDList -aALL -Nolog |egrep  "Media Error Count|SAS Address|Firmware state|Predictive Failure Count"')
    for h in info_all:
        data_all.append(h.strip())
    for i in data_all:
        info = i.strip("\n")
        name = info.split(":")[0]
        value = info.split(":")[1]
        if name == "Media Error Count":
            info_dict["Media Error Count"] = value.strip()
        elif name == "Firmware state":
            info_dict["Firmware state"] = value.strip()
        elif name == "Predictive Failure Count":
            info_dict["Predictive Failure Count"] = value.strip()
        elif name == "SAS Address(0)":
            info_dict["SAS Address(0)"] = value.strip()
            disk_info_format(info_dict)
        else:
            pass


def disk_info_format(args):
    global data_format
    if args["SAS Address(0)"]:
        val = {args["SAS Address(0)"]:{'Media Error Count':args['Media Error Count'],'Firmware state':args['Firmware state'],'Predictive Failure Count':args['Predictive Failure Count']}}
        data_format.update(val)

if __name__ == '__main__':
    disk_list_info()
#    os.popen('sudo rm -rf /etc/zabbix/scripts/MegaSAS.log')
    if data_format.get(arg):
        info = data_format.get(arg)
        if info.get("Media Error Count") != "0":
            print("2")
        elif info.get("Firmware state") == "Online, Spun Up"  and info.get("Predictive Failure Count") == "0":
            print("0")
        else:
            print("1")
    else:
        print("1")
disk-healthe.py最终版

 

 

三、部署zabbix监控环境(Linux)

  1、修改zabbix_agentd的配置文件,开启自定义脚本监控开关。

  vim   /etc/zabbix/zabbix_agentd.conf

      增加下面两项,开启自定义脚本开关,并制定脚本位置。

Include=/etc/zabbix/zabbix_agentd.conf.d/*.conf
UnsafeUserParameters=1

  2、查看zbbix配置文件会自动包含加载/etc/zabbix/zabbix_agentd.conf.d/这个目录下的conf配置文件。稍后我们将自定义的配置写到这个目录下。

  新建配置文件:  

vim  /etc/zabbix/zabbix_agentd.conf.d/disk-smart-health.conf
   键入如下内容
UserParameter=disk.discovery[*],/etc/zabbix/scripts/test/disk-discovery.py
UserParameter=disk.health[*],/etc/zabbix/scripts/test/disk-health.py $1

  别忘记了,将前面说过的脚本分别放到制定的路径下面,并赋予755权限。

  3、设定zabbix用户免密以sudo权限执行:

echo "zabbix ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/zabbix

  或者直接在 /etc/sudoers 这个文件中配置,先给予写权限: 

chmod +w /etc/sudoers
echo "zabbix  ALL=(ALL)       NOPASSWD:/usr/sbin/smartctl" >> /etc/sudoers
chmod -w /etc/sudoers

  重启zabbix,理论只需重启agent端即可:

service zabbix_agentd restart

  在zabbix server机器上测试下获取下自定义键值数据:

  这步很重要,先测试一下监控脚本能不能用,括号里面的数字是代表第几块硬盘,是什么状态,0代表正常,1证明故障。

  UserParameter=key[*],command
  key为唯一值,[*]表示参数。
  command为要执行的命令或脚本,key[*]里面的参数一一对应$1$9,一共9个参数。$0表示脚本命令。返回结果数据最大为512KB
  参数禁止使用下列字符:\ ‘ ” ` * ? [ ] { } ~ $ ! & ; ( ) <> | # @

  测试步骤:

  1、一般zabbix_get获取不到ip地址原因有几个,本机测试没问题,在本机上和zabbixserver上zabbix_get都获取不到数据,有人说在zabbix_agentd.conf里面的加上Timeout=10,加上超时参数。

    1、获取不到数据的主要原因是可能没有权限,在脚本里面需要执行命令的话,一定要加上sudo。

    2、尽量不适用文件操作比如python的with open,尽量都存在变量里面。

zabbix_get -s 192.168.8.253 -p10050 -k "disk.health[1]"

四、配置zabbix自动发现等配置

  1、这里我并没有单独创建一个模板,我这里是给对应的服务器里面配置了自动发现及监控。

  创建自动发现

  

  2、给自动发现创建监控项(通过输入硬盘编号,查看对应的硬盘信息检测返回值)

  

  

  3、给自动发现创建触发器(如果最后一次检测返回的值是1,就报警。)

  

  4、给自动发现创建触发器(方便查看历史记录)

  

  这里有话要说,因为我们判断是Media Error Count不等于0,Predictive Failure Count不等于0,Firmware state: Online, Spun Up 不是在线状态,就输出1,否则输出0。把SAS Address(0)作为唯一识别符,但是这篇博主所写的值得我们深思https://segmentfault.com/a/1190000011402256。

  所以这里我们增加一项触发器,就是Media Error Count不等于0的话输出2,最终版里面就是这么写的。这里我们让他触发严重,而不是灾难,当然你也可以选择一般严重。

  

 

 

四、Windows版

  一、准备环境

    1、安装python2.7以上,并添加环境变量,https://www.python.org/

    2、下载megacli的windows版,最前面我们说过。

    3、安装zabbix_agentd,这里可以参考原来的博客地址:https://www.cnblogs.com/lei0213/p/8858269.html

  二、为什么这里要单独写个windows版本呢,因为windows没有egrep这么命令,用的是findstr命令。而且路径等都不相同。

  1、在C盘创建三个文件夹,python,megacli,zabbix。分别把安装程序安装到这三个对应的目录里面。在zabbix下新建scripts目录,把自动发现和检查脚本放到此文件夹里面。

  

  2、自动发现脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os

data_all = []
info_dict = {}
data = {}
data_list= []

def disk_list_info():
    info_all = os.popen('C:\\megacli\\MegaCli64 -PDList -aALL | findstr "Media Error Count  Count Firmware state SAS Address"')
    for h in info_all:
        data_all.append(h.strip())
    for i in data_all:
        info = i.strip('\n')
        name=info.split(":")[0]
        value=info.split(":")[1]
        if name == "Media Error Count":
            info_dict["Media Error Count"] = value
        elif  name == "Firmware state":
            info_dict["Firmware state"] = value
        elif name == "SAS Address(0)":
            info_dict["SAS Address(0)"] = value
            disk_info_format(info_dict)
        else:
            pass


def disk_info_format(args):
    global data
    disk_name = {}
    if args["SAS Address(0)"]:
        disk_name["{#DISK_NAME}"] = args["SAS Address(0)"]
        data_list.append(disk_name)
    else:
        pass

if __name__ == '__main__':
    disk_list_info()
    os.popen('del C:\\Windows\\System32\\MegaSAS.log')
    data["data"] = data_list
    jsonStr = json.dumps(data)
    print(jsonStr)
disk-discovery.py

   线上最终版

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os

data_all = []
info_dict = {}
data = {}
data_list= []

def disk_list_info():
    info_all = os.popen('C:\\megacli\\MegaCli64 -PDList -aALL -Nolog | findstr "Media Error Count  Count Firmware state SAS Address"')
    for h in info_all:
        data_all.append(h.strip())
    for i in data_all:
        info = i.strip('\n')
        name=info.split(":")[0]
        value=info.split(":")[1]
        if name == "Media Error Count":
            info_dict["Media Error Count"] = value
        elif  name == "Firmware state":
            info_dict["Firmware state"] = value
        elif name == "SAS Address(0)":
            info_dict["SAS Address(0)"] = value
            disk_info_format(info_dict)
        else:
            pass


def disk_info_format(args):
    global data
    disk_name = {}
    if args["SAS Address(0)"]:
        disk_name["{#DISK_NAME}"] = args["SAS Address(0)"]
        data_list.append(disk_name)
    else:
        pass

if __name__ == '__main__':
    disk_list_info()
    data["data"] = data_list
    jsonStr = json.dumps(data)
    print(jsonStr)
disk-discovery.py 最终版

 

    3、检查脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os


arg = sys.argv[1]

data_all = []
info_dict = {}
data = []
data_format = {}
def disk_list_info():
    info_all = os.popen('C:\\megacli\\MegaCli64 -PDList -aALL | findstr "Media Error Count Predictive Failure Count Firmware state  SAS Address"')
    for h in info_all:
        data_all.append(h.strip())
    for i in data_all:
        info = i.strip("\n")
        name = info.split(":")[0]
        value = info.split(":")[1]
        if name == "Media Error Count":
            info_dict["Media Error Count"] = value.strip()
        elif name == "Firmware state":
            info_dict["Firmware state"] = value.strip()
        elif name == "Predictive Failure Count":
            info_dict["Predictive Failure Count"] = value.strip()
        elif name == "SAS Address(0)":
            info_dict["SAS Address(0)"] = value.strip()
            disk_info_format(info_dict)
        else:
            pass


def disk_info_format(args):
    global data_format
    if args["SAS Address(0)"]:
        val = {args["SAS Address(0)"]:{'Media Error Count':args['Media Error Count'],'Firmware state':args['Firmware state'],'Predictive Failure Count':args['Predictive Failure Count']}}
        data_format.update(val)

if __name__ == '__main__':
    disk_list_info()
    os.popen('del C:\\Windows\\System32\\MegaSAS.log')
    if data_format.get(arg):
        info = data_format.get(arg)
        if info.get("Firmware state") == "Online, Spun Up" and info.get("Media Error Count") == "0" and info.get("Predictive Failure Count") == "0":
            print("0")
        else:
            print("1")
    else:
        print("1")
disk-health.py

  线上最终版

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os


arg = sys.argv[1]

data_all = []
info_dict = {}
data = []
data_format = {}
def disk_list_info():
    info_all = os.popen('C:\\megacli\\MegaCli64 -PDList -aALL -Nolog | findstr "Media Error Count Predictive Failure Count Firmware state  SAS Address"')
    for h in info_all:
        data_all.append(h.strip())
    for i in data_all:
        info = i.strip("\n")
        name = info.split(":")[0]
        value = info.split(":")[1]
        if name == "Media Error Count":
            info_dict["Media Error Count"] = value.strip()
        elif name == "Firmware state":
            info_dict["Firmware state"] = value.strip()
        elif name == "Predictive Failure Count":
            info_dict["Predictive Failure Count"] = value.strip()
        elif name == "SAS Address(0)":
            info_dict["SAS Address(0)"] = value.strip()
            disk_info_format(info_dict)
        else:
            pass


def disk_info_format(args):
    global data_format
    if args["SAS Address(0)"]:
        val = {args["SAS Address(0)"]:{'Media Error Count':args['Media Error Count'],'Firmware state':args['Firmware state'],'Predictive Failure Count':args['Predictive Failure Count']}}
        data_format.update(val)

if __name__ == '__main__':
    disk_list_info()
    if data_format.get(arg):
        info = data_format.get(arg)
        if info.get("Media Error Count") != "0":
            print("2")
        elif info.get("Firmware state") == "Online, Spun Up" and info.get("Predictive Failure Count") == "0":
            print("0")
        else:
            print("1")
    else:
        print("1")
disk-health.py 最终版

 

  4、在C:\zabbix\zabbix_agentd.conf.d\这个目录下新建配置文件disk-smart-health.conf,并将内容填写进去。

UserParameter=disk.discovery[*],C:\zabbix\scripts\disk-discovery.py
UserParameter=disk.health[*],C:\zabbix\scripts\disk-health.py $1
disk-smart-health.conf

   5、修改zabbix_agentd.win.conf,启用脚本监控。

Include=C:\zabbix\zabbix_agentd.conf.d\*.conf
UnsafeUserParameters=1

  6、重启zabbix_agentd服务。

  7、如第四大标题一样,zabbix server里面添加自动发现等信息,你要是嫌麻烦,可以直接再模板里新建,以后就可以重复使用了。

 注意!!!

  1、在监控windows 服务器过程中出现过 Zabbix agent item "disk.discovery" on host "服务器监控名称" failed: first network error, wait for 90 seconds错误,是因为zabbix的客户端配置文件里面的Timeout文件默认是3秒导致的,改成30秒就OK了,如果还不行,就需要将zabbix服务端的配置文件里面的Timeout文件也改成30秒,就OK了。

  2、我的自动发现开始的时候,都是在每个监控主机里面建的,你可以直接在模板里面新建,这样用着方便。

  3、千万记得每次改完脚本或者配置文件,一定要重启zabbix_agentd服务。

 

posted @ 2019-07-03 17:37  Charles.L  阅读(2871)  评论(0编辑  收藏  举报