1、库版本
- python 3.6
- pysnmp 4.4
2、简单的get请求
测试环境,基于本机电脑 snmp v1版本进行调试的。
g = getCmd(SnmpEngine(), # 创建SNMP引擎
CommunityData('xxxxxx'), # 团体属性
UdpTransportTarget((ip, 161), timeout=1, retries=0), # 认证
ContextData(), # 创建SNMP上下文信息
ObjectType(ObjectIdentity(oid)) # 创建MIB节点对象
)
3、遇到的问题
可能会遇到:TypeError: () takes 3 positional arguments but 4 were given。这个报错
详情请见 https://github.com/pyasn1/pyasn1/issues/28
3、完整代码
from pysnmp.hlapi import *
from pysnmp.error import PySnmpError
class NetSNMP(object):
"""
基于pySnmp的封装,支持v1、v2c、v3版本连接
----------
version(int)
*必填
版本号(1、2、3)
ip(str)
*必填
ip地址(0.0.0.0)
mibName(str)
*选填,默认None
要访问的 MIB 模块的名称(SNMPv2-MIB)
objectName(str)
*选填,默认None
要访问的对象的名称(sysName)
oid(str)
*选填,默认None
oid(1.3.6.1.2.1.1.1)
timeout(int)
*选填,默认1
超时时间(s)
retries(int)
*选填,默认0
重试次数(1)
mib_list(dict)
[{"key":"IF-MIB","value":"ifDescr"}]
*选填,多个mib列表
oid_list
["oid","oid"...]
*选填,多个oid列表
----------
查询优先级:oid、mib、oidList、mibList
"""
def __init__(self, version=1, ip=None, mibName=None, objectName=None, oid=None, data=None, timeout=1, retries=0,
mib_list=None, oid_list=None):
self.version = version
self.ip = ip
self.mibName = mibName
self.objectName = objectName
self.data = data
self.oid = oid
self.timeout = timeout
self.retries = retries
self.mib_list = mib_list
self.oid_list = oid_list
self.Community = None
# 公共参数
def com(self):
# 初始化引擎
engine = SnmpEngine()
# 配置目标主机
target = UdpTransportTarget((self.data["ip"], self.data["port"]), timeout=self.timeout, retries=self.retries)
# 实例化上下文对象
context = ContextData()
return engine, target, context
# get方式getCmd
def get(self):
res = self.com()
engine = res[0]
target = res[1]
context = res[2]
lookupMib = False
if self.oid:
obj = ObjectType(ObjectIdentity(self.oid))
else:
lookupMib = True
obj = ObjectType(ObjectIdentity(self.mibName, self.objectName, 0))
errList = []
for i in range(self.retries + 1):
g = getCmd(engine, self.Community, target, context, obj, lookupMib=lookupMib)
try:
errorIndication, errorStatus, errorIndex, varBinds = next(g)
if errorIndication or errorStatus:
# 处理 SNMP 异常
raise PySnmpError(errorIndication)
else:
# 打印输出
for i in varBinds:
data = {
"code": 200,
"result": str(i[1])
}
return data
except PySnmpError as e:
if i < self.retries:
# 处理超时异常,进行重试
err = f"连接超时, 重试次数 ({i + 1}/{self.retries})..."
errList.append(err)
else:
err = f"连接异常,重试次数: {self.retries} 异常信息: {e}"
errList.append(err)
data = {
"code": 500,
"result": errList
}
return data
# get多个oid/mib方式getCmd
def getList(self):
res = self.com()
engine = res[0]
target = res[1]
context = res[2]
obj = []
lookupMib = False
if self.oid_list is not None:
for o in self.oid_list:
obj.append(ObjectType(ObjectIdentity(o)))
elif self.mib_list:
lookupMib = True
for o in self.mib_list:
obj.append(ObjectType(ObjectIdentity(o["key"], o["value"], 0)))
errList = []
resList = []
for i in range(self.retries + 1):
g = getCmd(engine, self.Community, target, context, *obj, lookupMib=lookupMib)
try:
errorIndication, errorStatus, errorIndex, varBinds = next(g)
if errorIndication or errorStatus:
# 处理 SNMP 异常
raise PySnmpError(errorIndication)
else:
# 打印输出
for key, value in enumerate(varBinds):
name = str(value[0])
if self.mib_list:
name = self.mib_list[key]["value"]
arr = {
"name": name,
"res": value[1].prettyPrint(),
}
resList.append(arr)
data = {
"code": 200,
"result": resList
}
return data
except PySnmpError as e:
if i < self.retries:
# 处理超时异常,进行重试
err = f"连接超时, 重试次数 ({i + 1}/{self.retries})..."
errList.append(err)
else:
err = f"连接异常,重试次数: {self.retries} 异常信息: {e}"
errList.append(err)
data = {
"code": 500,
"result": errList
}
return data
# walk方式nextCmd
def walk(self):
res = self.com()
engine = res[0]
target = res[1]
context = res[2]
lookupMib = False
if self.oid:
obj = ObjectType(ObjectIdentity(self.oid))
else:
lookupMib = True
obj = ObjectType(ObjectIdentity(self.mibName, self.objectName))
errList = []
for i in range(self.retries + 1):
g = nextCmd(engine, self.Community, target, context, obj, lexicographicMode=False, lookupMib=lookupMib)
try:
errorIndication, errorStatus, errorIndex, varBinds = next(g)
if errorIndication or errorStatus:
# 处理 SNMP 异常
raise PySnmpError(errorIndication)
else:
s = []
for a, b, c, d in g:
if d[0][1]:
res = d[0][1]
s.append(str(res))
else:
s.append(str(d[0][1]))
data = {
"code": 200,
"result": s
}
return data
except PySnmpError as e:
if i < self.retries:
# 处理超时异常,进行重试
err = f"连接超时, 重试次数 ({i + 1}/{self.retries})..."
errList.append(err)
else:
err = f"连接异常,重试次数: {self.retries} 异常信息: {e}"
errList.append(err)
data = {
"code": 500,
"result": errList
}
return data
# walk多oid方式nextCmd
def walkList(self):
res = self.com()
engine = res[0]
target = res[1]
context = res[2]
obj = []
lookupMib = False
if self.oid_list is not None:
for o in self.oid_list:
obj.append(ObjectType(ObjectIdentity(o)))
elif self.mib_list:
lookupMib = False
for o in self.mib_list:
obj.append(ObjectType(ObjectIdentity(o["key"], o["value"])))
errList = []
for i in range(self.retries + 1):
g = nextCmd(engine, self.Community, target, context, *obj, lexicographicMode=False, lookupMib=lookupMib)
try:
errorIndication, errorStatus, errorIndex, varBinds = next(g)
varBinds = []
if errorIndication or errorStatus:
# 处理 SNMP 异常
raise PySnmpError(errorIndication)
else:
for _, _, _, v in g:
varBinds.extend(v)
result = {}
for varBind in varBinds:
oid = str(varBind[0])
value = varBind[1].prettyPrint()
mib = '.'.join(oid.split('.')[:-1])
if mib not in result:
result[mib] = []
result[mib].append({oid: value})
s = []
if self.mib_list:
for key, value in enumerate(result):
arr = {}
arr["name"] = self.mib_list[key]["value"]
arr["res"] = result[value]
s.append(arr)
else:
s = result
data = {
"code": 200,
"result": s
}
return data
except PySnmpError as e:
print(e)
if i < self.retries:
# 处理超时异常,进行重试
err = f"连接超时, 重试次数 ({i + 1}/{self.retries})..."
errList.append(err)
else:
err = f"连接异常,重试次数: {self.retries} 异常信息: {e}"
errList.append(err)
data = {
"code": 500,
"result": errList
}
return data
# V1
def snmpV1(self, type):
"""
snmp v1版本
----------
type(str)
类型 (get、walk)
----------
"""
self.Community = CommunityData(self.data["pwd"], mpModel=0)
if type == 'get':
res = self.get()
elif type == 'getList':
res = self.getList()
elif type == 'walkList':
res = self.walkList()
else:
res = self.walk()
return res
# V2
def snmpV2(self, type):
"""
snmp v2c版本
----------
type(str)
类型 (get、walk)
----------
"""
self.Community = CommunityData(self.data["pwd"], mpModel=1)
if type == 'get':
res = self.get()
elif type == 'getList':
res = self.getList()
elif type == 'walkList':
res = self.walkList()
else:
res = self.walk()
return res
# V3
def snmpV3(self, type):
"""
snmp v3版本,支持md5、sha认证加密
----------
type(str)
类型 (get、walk)
----------
"""
authProtocol = self.data["authProtocol"]
privProtocol = self.data["privProtocol"]
user = self.data["user"]
authKey = self.data["authKey"]
privKey = self.data["privKey"]
# md5加密
if authProtocol == 'md5':
if privProtocol == 'des':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACMD5AuthProtocol,
privProtocol=usmDESPrivProtocol,
)
elif privProtocol == '3des':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACMD5AuthProtocol,
privProtocol=usm3DESEDEPrivProtocol,
)
elif privProtocol == 'aes128':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACMD5AuthProtocol,
privProtocol=usmAesCfb128Protocol,
)
elif privProtocol == 'aes192':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACMD5AuthProtocol,
privProtocol=usmAesCfb192Protocol,
)
elif privProtocol == 'des':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACMD5AuthProtocol,
privProtocol=usmAesCfb256Protocol,
)
else:
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=None,
authProtocol=usmHMACMD5AuthProtocol,
privProtocol=usmNoPrivProtocol,
)
# sha加密
if authProtocol == 'sha':
if privProtocol == 'des':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmDESPrivProtocol,
)
elif privProtocol == '3des':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usm3DESEDEPrivProtocol,
)
elif privProtocol == 'aes128':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol,
)
elif privProtocol == 'aes192':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb192Protocol,
)
elif privProtocol == 'des':
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=privKey,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb256Protocol,
)
else:
self.Community = UsmUserData(
userName=user,
authKey=authKey,
privKey=None,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmNoPrivProtocol,
)
# no auth no priv
if authProtocol is None and privProtocol is None:
self.Community = UsmUserData(
userName=user,
authKey=None,
privKey=None,
authProtocol=usmNoAuthProtocol,
privProtocol=usmNoPrivProtocol,
)
if type == 'get':
res = self.get()
elif type == 'getList':
res = self.getList()
elif type == 'walkList':
res = self.walkList()
else:
res = self.walk()
return res
# snmp的get
def getSnmp(self):
"""
version:版本(1,2,3)
mibName: mib库
mib: MIB对象
ip:IP地址
port:端口号
"""
if self.version == 1:
return self.snmpV1('get')
elif self.version == 2:
return self.snmpV2('get')
elif self.version == 3:
return self.snmpV3('get')
else:
return False
# snmp的WALK
def walkSnmp(self):
"""
version:版本(1,2,3)
oid: oid
ip:IP地址
port:端口号
"""
if self.version == 1:
return self.snmpV1('walk')
elif self.version == 2:
return self.snmpV2('walk')
elif self.version == 3:
return self.snmpV3('walk')
else:
return False
# snmp的getList
def getListSnmp(self):
"""
version:版本(1,2,3)
oid: oid
ip:IP地址
port:端口号
"""
if self.version == 1:
return self.snmpV1('getList')
elif self.version == 2:
return self.snmpV2('getList')
elif self.version == 3:
return self.snmpV3('getList')
else:
return False
# snmp的walkList
def walkListSnmp(self):
"""
version:版本(1,2,3)
oid: oid
ip:IP地址
port:端口号
"""
if self.version == 1:
return self.snmpV1('walkList')
elif self.version == 2:
return self.snmpV2('walkList')
elif self.version == 3:
return self.snmpV3('walkList')
else:
return False
if __name__ == '__main__':
ip = "你的ip"
data = {
"ip": ip,
"port": 161,
"pwd": "public",
}
walk_oid_list = [
"1.3.6.1.2.1.2.2.1.8",
"1.3.6.1.2.1.2.2.1.3",
]
walk_mib_list = [
{"key": "IF-MIB", "value": "ifOperStatus"},
{"key": "IF-MIB", "value": "ifType"}
]
get_mib_list = [
{"key": "SNMPv2-MIB", "value": "sysDescr"},
{"key": "SNMPv2-MIB", "value": "sysName"}
]
get_oid_list = [
"1.3.6.1.2.1.1.1.0",
"1.3.6.1.2.1.1.5.0"
]
"""
walk示例
"""
# walk示例
walkSnmp = NetSNMP(version=1, ip=ip, data=data, mibName="IF-MIB", objectName="ifOperStatus")
res_walk = walkSnmp.walkSnmp()
# {'code': 200, 'result': ['up', 'notPresent', 'down', 'down', 'up', 'notPresent', 'down', 'notPresent', 'notPresent', 'up', 'down', 'up']}
# walk多mib示例
walkListSnmp_mib = NetSNMP(version=1, ip=ip, data=data, mib_list=walk_mib_list)
res_walk_list_mib = walkListSnmp_mib.walkListSnmp()
# {'code': 200, 'result': [{'name': 'ifOperStatus', 'res': [{'1.3.6.1.2.1.2.2.1.8.2': '1'},...]}]}
# walk多oid示例
walkListSnmp_oid = NetSNMP(version=1, ip=ip, data=data, oid_list=walk_oid_list)
res_walk_list_oid = walkListSnmp_oid.walkListSnmp()
# {'code': 200, 'result': {'1.3.6.1.2.1.2.2.1.8': [{'1.3.6.1.2.1.2.2.1.8.2': '1'}, {'1.3.6.1.2.1.2.2.1.8.3': '6'},...]}}
"""
get示例
"""
# get示例
getSnmp = NetSNMP(version=1, ip=ip, data=data, mibName="SNMPv2-MIB", objectName="sysDescr")
res_get = getSnmp.getSnmp()
# {'code': 200, 'result': 'Hardware: AMD64 Family 25 Model 80 Stepping 0 AT/AT COMPATIBLE - Software: Windows Version 6.3 (Build 22000 Multiprocessor Free)'}
# get多mib示例
getListSnmp_mib = NetSNMP(version=1, ip=ip, data=data, mib_list=get_mib_list)
res_get_list_mib = getListSnmp_mib.getListSnmp()
# {'code': 200, 'result': [{'name': 'sysDescr', 'res': 'Hardware: AMD64 Family 25 Model 80 Stepping 0 AT/AT COMPATIBLE - Software: Windows Version 6.3 (Build 22000 Multiprocessor Free)'}, {'name': 'sysName', 'res': 'ChenXu'}]}
# get多oid示例
getListSnmp_oid = NetSNMP(version=1, ip=ip, data=data, oid_list=get_oid_list)
res_get_list_oid = getListSnmp_oid.getListSnmp()
# {'code': 200, 'result': [{'name': '1.3.6.1.2.1.1.1.0', 'res': 'Hardware: AMD64 Family 25 Model 80 Stepping 0 AT/AT COMPATIBLE - Software: Windows Version 6.3 (Build 22000 Multiprocessor Free)'}, {'name': '1.3.6.1.2.1.1.5.0', 'res': 'ChenXu'}]}