• Python通过SNMP监控网络设备


    前段时间,为了实现自动化巡检,我开发了自动化巡检工具,由于我的系统设备版本比较多,所以我是分别开发的客户端程序,服务端使用dll文件与客户端通信,服务端的dll在与python通信,通过Python丰富的第三方库,实现绘图入库等,该方式比较繁琐,我们管理的设备还有一些网络设备,这些设备无法通过开发程序来实现监控,为了实现全平台全设备监控,我决定使用SNMP实现监控任务。

    首先需要在系统中安装SNMP客户端,对于Linux平台来说只需要执行如下配置过程即可.

    [root@localhost ~]# yum install -y net-snmp
    [root@localhost ~]# cat /etc/snmp/snmpd.conf |grep -vE "^#|^$"
    com2sec notConfigUser  default       public
    
    group   notConfigGroup v1           notConfigUser
    group   notConfigGroup v2c           notConfigUser
    
    view    systemview    included   .1
    view    systemview    included   .1
    
    access  notConfigGroup  ""  any  noauth  exact  systemview none none
    
    [root@localhost ~]# systemctl restart snmpd
    [root@localhost ~]# systemctl enable snmpd
    

    如果是Windows系统则需要在客户机服务列表,开启SNMP支持,并设置好一个团体名称,如下图。

    当我们配置好客户端后,服务端就客户获取数据了,我们以一个OID序号为例,我们查询特定序号对应的名称,然后将其记录下来,例如下面这样。

    首先我们不适用PySNMP模块直接开线程调用看看,该代码如下所示.

    import os,re,time
    
    # 通过SNMP收集主机CPU利用率: 通过SNMP协议,收集目标主机的CPU利用率(百分比),并返回JSON字符串.
    def Get_CPU_Info(addr):
        try:
            Head = ["HostName","CoreLoad","CpuUser","CpuSystem","CpuIdle"]
            CPU = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.1.5")
            CPU.append(ret.read().split(":")[3].strip())
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.25.3.3.1.2")
            CPU.append(ret.read().split(":")[3].strip())
    
            for i in [9,10,11]:
                ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " 1.3.6.1.4.1.2021.11.{}.0".format(i))
                ret = ret.read()
                Info = ret.split(":")[3].strip()
                CPU.append(Info)
            return dict(zip(Head,CPU))
        except Exception:
            return 0
    
    # 通过SNMP获取系统CPU负载信息: 分别获取到系统的1,5,15分钟的负载信息,并返回JSON格式.
    def Get_Load_Info(addr):
        try:
            Head = ["HostName","Load1","Load5","Load15"]
            SysLoad = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.1.5")
            SysLoad.append(ret.read().split(":")[3].strip())
    
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.4.1.2021.10.1.3")
            load = list(re.sub(".*STRING: ", "", ret.read()).split("\n"))
            SysLoad.append(load[0])
            SysLoad.append(load[1])
            SysLoad.append(load[2])
            return dict(zip(Head,SysLoad))
        except Exception:
            return 0
    
    # 通过SNMP获取系统内存占用: 内存利用率,获取到之后,将其转化为字典格式保存。
    def Get_Mem_Info(addr):
        try:
            Head = ["HostName","memTotalSwap","memAvailSwap","memTotalReal","memTotalFree"]
            SysMem = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.1.5")
            SysMem.append(ret.read().split(":")[3].strip())
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.4.1.2021.4")
            mem = ret.read().split("\n")
            for i in [2,3,4,6]:
                SysMem.append(re.sub(".*INTEGER: ","",mem[i]).split(" ")[0])
            return dict(zip(Head,SysMem))
        except Exception:
            return 0
    
    # 通过SNMP获取系统磁盘数据: 这个案例并不完整,我只写了一点,后面有个问题一直没有解决.
    def Get_Disk_Info(addr):
        try:
            dic = {}
            list = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " HOST-RESOURCES-MIB::hrStorageDescr")
            DiskName = ret.read().split("\n")
            ret =os.popen("snmpwalk -v 2c -c nmap " + addr + " HOST-RESOURCES-MIB::hrStorageUsed")
            DiskUsed = ret.read().split("\n")
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " HOST-RESOURCES-MIB::hrStorageSize")
            DiskSize = ret.read().split("\n")
    
            for i in range(1,len(DiskName) - 7):
                dic["Name"]= DiskName[i + 5].split(":")[3]
                dic["Used"]= DiskUsed[i + 5].split(":")[3]
                dic["Size"]= DiskSize[i + 5].split(":")[3]
                list.append(dic)
            return list
        except Exception:
            return 0
    
    if __name__ == '__main__':
        for i in range(100):
            dic = Get_CPU_Info("192.168.1.20")
            print(dic)
            time.sleep(1)
    

    通过SNMP收集主机CPU利用率 通过SNMP协议,收集目标主机的CPU利用率(百分比),并返回JSON字符串.

    import os,re,time
    
    def Get_CPU_Info(addr):
        try:
            Head = ["HostName","CoreLoad","CpuUser","CpuSystem","CpuIdle"]
            CPU = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.1.5")
            CPU.append(ret.read().split(":")[3].strip())
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.25.3.3.1.2")
            CPU.append(ret.read().split(":")[3].strip())
    
            for i in [9,10,11]:
                ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " 1.3.6.1.4.1.2021.11.{}.0".format(i))
                ret = ret.read()
                Info = ret.split(":")[3].strip()
                CPU.append(Info)
            return dict(zip(Head,CPU))
        except Exception:
            return 0
    
    if __name__ == '__main__':
        for i in range(100):
            dic = Get_CPU_Info("192.168.1.20")
            print(dic)
            time.sleep(1)
    

    通过SNMP获取系统CPU负载信息 分别获取到系统的1,5,15分钟的负载信息,并返回JSON格式.

    import os,re,time
    
    def Get_Load_Info(addr):
        try:
            Head = ["HostName","Load1","Load5","Load15"]
            SysLoad = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.1.5")
            SysLoad.append(ret.read().split(":")[3].strip())
    
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.4.1.2021.10.1.3")
            load = list(re.sub(".*STRING: ", "", ret.read()).split("\n"))
            SysLoad.append(load[0])
            SysLoad.append(load[1])
            SysLoad.append(load[2])
            return dict(zip(Head,SysLoad))
        except Exception:
            return 0
    
    if __name__ == '__main__':
        dic = Get_Load_Info("192.168.1.20")
        print(dic)
    

    通过SNMP获取系统内存占用 内存利用率,获取到之后,将其转化为字典格式保存。

    import os,re,time
    
    def Get_Mem_Info(addr):
        try:
            Head = ["HostName","memTotalSwap","memAvailSwap","memTotalReal","memTotalFree"]
            SysMem = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.2.1.1.5")
            SysMem.append(ret.read().split(":")[3].strip())
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " .1.3.6.1.4.1.2021.4")
            mem = ret.read().split("\n")
            for i in [2,3,4,6]:
                SysMem.append(re.sub(".*INTEGER: ","",mem[i]).split(" ")[0])
            return dict(zip(Head,SysMem))
        except Exception:
            return 0
    
    if __name__ == '__main__':
        dic = Get_Mem_Info("192.168.1.20")
        print(dic)
    

    通过SNMP获取系统磁盘数据 这个案例并不完整,我只写了一点,后面有个问题一直没有解决.

    import os,re,time
    
    def Get_Disk_Info(addr):
        try:
            dic = {}
            list = []
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " HOST-RESOURCES-MIB::hrStorageDescr")
            DiskName = ret.read().split("\n")
            ret =os.popen("snmpwalk -v 2c -c nmap " + addr + " HOST-RESOURCES-MIB::hrStorageUsed")
            DiskUsed = ret.read().split("\n")
            ret = os.popen("snmpwalk -v 2c -c nmap " + addr + " HOST-RESOURCES-MIB::hrStorageSize")
            DiskSize = ret.read().split("\n")
    
            for i in range(1,len(DiskName) - 7):
                dic["Name"]= DiskName[i + 5].split(":")[3]
                dic["Used"]= DiskUsed[i + 5].split(":")[3]
                dic["Size"]= DiskSize[i + 5].split(":")[3]
                list.append(dic)
            return list
        except Exception:
            return 0
    
    if __name__ == '__main__':
         list = Get_Disk_Info("192.168.1.20")
         print(list)
    

    接下来,我们使用pysnmp模块来做,安装pysnmp很简单,执行命令pip install pysnmp即可,安装后,使用以下代码执行即可获取到目标数据,网上的那些转载的都是坑,没一个能用的,这个案例是官方案例,可以使用。

    from pysnmp.hlapi import *
    
    iterator = getCmd(SnmpEngine(),
                      CommunityData('public'),
                      UdpTransportTarget(('192.168.1.113', 161)),
                      ContextData(),
                      ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
    
    errorIndication, errorStatus, errorIndex, varBinds = next(iterator)
    
    if errorIndication:
        print(errorIndication)
    else:
        if errorStatus:
            print('%s at %s' % (errorStatus.prettyPrint(), varBinds[int(errorIndex)-1] if errorIndex else '?'))
        else:
            for varBind in varBinds:
                print(' = '.join([x.prettyPrint() for x in varBind]))
    

    首先我们以一个OID序号为例,我们查询特定序号对应的名称,然后将其记录下来,例如下面这样。

    在客户机上面,需要在服务列,开启SNMP支持,并设置好一个团体名称,如下图。

    然后我们简单的封装一个类,先来测试一下是否能通。

    # snmpwalk -v 2c -c public 192.168.1.113 .1.3.6.1.2.1.1.5
    from pysnmp.hlapi import *
    
    
    class NetSNMP():
        def __init__(self,address,region):
            self.region = region
            self.address = address
    
        # 获取指定数据的方法
        def GetNumber(self,oid,sub_oid,sub_id):
            iterator = getCmd(SnmpEngine(),
                              CommunityData(self.region),
                              UdpTransportTarget((self.address, 161)),
                              ContextData(),
                              ObjectType(ObjectIdentity(oid, sub_oid, sub_id)))
            errorIndication, errorStatus, errorIndex, varBinds = next(iterator)
    
            if errorIndication:
                return False
            else:
                if errorStatus:
                    return False
                else:
                    for varBind in varBinds:
                        return [x.prettyPrint() for x in varBind]
    
    if __name__ == "__main__":
    
        # 初始化
        ptr = NetSNMP("192.168.1.101","public")
    
        # 设置OID数据集
        ret = ptr.GetNumber("HOST-RESOURCES-MIB","hrMemorySize",0)
        print("类型: {} --> 返回结果: {} --> 解析: {}".format(type(ret),ret,ret[1]))
    

    运行后,即可读取到内存数据,如下。


    未完待续

  • 相关阅读:
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    72. Edit Distance
    583. Delete Operation for Two Strings
    582. Kill Process
    indexDB基本用法
    浏览器的渲染原理
    js实现txt/excel文件下载
    git 常用命令
    nginx进入 配置目录时
  • 原文地址:https://www.cnblogs.com/LyShark/p/14374701.html
Copyright © 2020-2023  润新知