Python 封装SNMP调用接口

PySNMP 是一个纯粹用Python实现的SNMP,用PySNMP的最抽象的API为One-line Applications,其中有两类API:同步的和非同步的,都在模块pysnmp.entity.rfc3413.oneliner.cmdgen 中实现,如下是Get方式与Walk方式的基本实现.

首先需要在系统中安装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支持,并设置好一个团体名称,如下图。

Python 封装SNMP调用接口

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

C:Usersadmin> snmpwalk -v 2c -c public 192.168.1.101 .1.3.6.1.2.1.25.2.2 HOST-RESOURCES-MIB::hrMemorySize.0 = INTEGER: 2096632 KBytes 

首先我们不使用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) 

我们使用pysnmp模块来做,安装pysnmp很简单,执行命令pip install pysnmp 即可,安装后使用以下代码执行即可获取到目标数据,获取方式分为两种一种为Get另一种为Walk.

from pysnmp.hlapi import * import os,sys  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]      # 使用Walk拉取数据     def WalkNumber(self, oid):         res = []         for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(SnmpEngine(),              CommunityData(self.region),UdpTransportTarget((self.address, 161)),ContextData(),              ObjectType(ObjectIdentity(oid)).addMibSource(              './site-packages/pysnmp/smi/mibs','pysnmp_mibs'),lexicographicMode=False):             if errorIndication:                 print(errorIndication, file=sys.stderr)                 break             elif errorStatus:                 print('%s at %s' % (errorStatus.prettyPrint(),                                     errorIndex and varBinds[int(errorIndex) - 1][0] or '?'),                       file=sys.stderr)                 break             else:                 for varBind in varBinds:                     res.append(str(varBind))         return res  if __name__ == "__main__":      # 初始化     ptr = NetSNMP("192.168.81.130","public")      # 使用GET方式获取OID数据     ret = ptr.GetNumber("HOST-RESOURCES-MIB","hrMemorySize",0)     print("类型: {} --> 返回结果: {} --> 解析: {}".format(type(ret),ret,ret[1]))      # 使用Walk方式获取OID数据     ret = ptr.WalkNumber(".1.3.6.1.2.1.2.2.1.6")     for each in ret:         mac = each.split("=")[1]         if len(mac) > 1:             print("网卡接口: {}".format(mac)) 

发表评论

相关文章