PySNMP发送自定义OID的SNMP Trap异常问题求助
我想用自定义OID发送SNMP Trap,命令行执行的命令如下:
$ snmptrap -v 2c -c '' 1.9.9.9.0 1.9.9.9.1 i 1 1.9.9.9.8 s "text"
尝试用PySNMP实现相同功能,参考官方文档写了如下代码:
g = sendNotification( SnmpEngine(), CommunityData(community_string, mpModel=1), UdpTransportTarget((host, 162)), ContextData(), 'trap', NotificationType( ObjectIdentity('1.9.9.9.0'), objects={ '1.9.9.9.1': 1, '1.9.9.9.8': 'text' } ) )
脚本能发送消息,但Wireshark捕获到的只有OID 1.9.9.9.0的Trap,指定的objects没有附带。
后来改用.addVarBinds()添加额外OID,代码如下:
# Assemble MIB viewer mibBuilder = builder.MibBuilder() # raw mibs compiler.addMibCompiler(mibBuilder, sources=['http://mibs.snmplabs.com/asn1/@mib@', '/.']) mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB', 'MY-MIB') mibView = view.MibViewController(mibBuilder) # send Trap g = sendNotification( SnmpEngine(), CommunityData(community_string, mpModel=1), UdpTransportTarget((host, 162)), ContextData(), 'trap', NotificationType( ObjectIdentity('1.9.9.9.0').addVarBinds( ObjectType(ObjectIdentity('1.9.9.9.1'), Integer(1)), ObjectType(ObjectIdentity('1.9.9.9.8'), OctetString("text")) ).resolveWithMib(mibView) ) )
此时出现错误,无法发送Trap,错误信息:
pysnmp: StatusInformation: {'errorIndication': NotInView('Requested OID is out of MIB view')}
但单独解析单个ObjectType是正常的:
obj = ObjectType(ObjectIdentity('1.9.9.9.1'), Integer(1)) print(obj.resolveWithMib(mibView))
请问该如何正确发送带自定义对象的Trap?问题出在哪里?
第一个代码的问题
你用NotificationType的objects参数时,PySNMP默认会尝试将这些OID关联到对应MIB定义的通知类型(比如TRAP-TYPE或NOTIFICATION-TYPE)。如果1.9.9.9.0不是标准MIB里定义的通知类型,PySNMP找不到对应的绑定关系,就会忽略objects参数里的内容。
第二个代码的问题
.addVarBinds()应该给NotificationType调用,而不是给ObjectIdentity添加——后者只是OID标识,不是通知类型容器。另外,加载自定义MIB后触发的视图检查错误,是因为PySNMP会验证OID是否在MIB视图范围内,而你的自定义MIB可能没有正确配置视图,或者resolveWithMib的调用方式有误。
正确实现方式
不需要加载自定义MIB(除非你想用MIB名称代替OID),直接构造完整的VarBind列表,绕过MIB关联逻辑,就能实现和命令行完全一致的效果:
from pysnmp.hlapi import * community_string = '' host = '1.9.9.9' # 替换为你的目标主机地址 errorIndication, errorStatus, errorIndex, varBinds = next( sendNotification( SnmpEngine(), CommunityData(community_string, mpModel=1), # mpModel=1对应SNMPv2c UdpTransportTarget((host, 162)), ContextData(), 'trap', # 指定发送SNMPv2c TRAP NotificationType( ObjectIdentity('1.9.9.9.0') ).addVarBinds( ObjectType(ObjectIdentity('1.9.9.9.1'), Integer(1)), ObjectType(ObjectIdentity('1.9.9.9.8'), OctetString("text")) ) ) ) if errorIndication: print(errorIndication) else: print("Trap发送成功")
关键说明
- 给
NotificationType调用.addVarBinds(),这样额外的OID会被作为Trap的附加变量绑定发送。 - 直接用原始OID构造
ObjectType,不需要加载自定义MIB,避免MIB视图检查的问题。 - 确保
mpModel=1,和命令行的-v 2c版本一致。
如果一定要用自定义MIB,需要确保MIB中正确定义了1.9.9.9.0这个通知类型,并且包含对应的附加对象绑定,否则PySNMP还是无法识别。但如果只是想发送自定义OID的Trap,上面的无MIB方式更直接高效。
内容的提问来源于stack exchange,提问作者user22332030

