• 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]))
    

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


    未完待续

  • 相关阅读:
    多线程--ThreadLocal类
    常用开发类库支持--UUID及空值处理Optional
    国际化的程序实现及其原理
    浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象
    使用批处理命令注册运行mysql数据库,无需注册mysql服务,可以在任意电脑登录使用
    计算机中位、字长、字的区别
    SQL Server用户自定义数据类型
    简单的回合制小游戏
    单链表创建、删除、查找、插入之C语言实现
    LeetCode-905 Sort Array By Parity Solution (with Java)
  • 原文地址:https://www.cnblogs.com/LyShark/p/14374701.html
Copyright © 2020-2023  润新知