端口1161的SNMP Agent:Net-SNMP查询超时问题排查
自定义PySNMP Agent无响应问题的修复方案
修复后的完整Agent代码
from pysnmp.hlapi import * from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdrsp, context from pysnmp.carrier.asyncore.dgram import udp from pysnmp.smi import exval import psutil # 创建SNMP引擎 snmpEngine = engine.SnmpEngine() # 自定义MIB对应的OID CPU_OID = '1.3.6.1.4.1.9999.2' # MY-MIB::cpuUtil MEMORY_OID = '1.3.6.1.4.1.9999.1' # MY-MIB::memoryUtil DISK_OID = '1.3.6.1.4.1.9999.3' # MY-MIB::diskUtil def get_cpu_usage(): """CPU使用率(百分比)""" return int(psutil.cpu_percent(interval=1)) def get_memory_usage(): """内存使用率(百分比)""" memory = psutil.virtual_memory() return int(memory.used * 100 / memory.total) def get_disk_usage(): """磁盘使用率(主分区,百分比)""" disk = psutil.disk_usage('/') return int(disk.used * 100 / disk.total) def create_variable_binds(oid, value): return [ObjectType(ObjectIdentity(oid), Integer32(value))] def create_snmp_agent(): """监听GET请求的SNMP Agent""" def process_snmp_request(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx): """处理SNMP GET请求""" oid, = [x[0] for x in varBinds] oid_str = str(oid) print("收到请求OID:", oid_str) # 精确匹配OID,避免前缀匹配误判 if oid_str == CPU_OID: value = get_cpu_usage() varBinds = create_variable_binds(oid, value) elif oid_str == MEMORY_OID: value = get_memory_usage() varBinds = create_variable_binds(oid, value) elif oid_str == DISK_OID: value = get_disk_usage() varBinds = create_variable_binds(oid, value) else: # 未知OID返回标准SNMP错误 varBinds = [(oid, exval.noSuchInstance)] cmdrsp.sendVarBinds(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx) # 配置SNMPv2c社区字符串(必须步骤,否则Agent无法识别合法请求) config.addCommunity( snmpEngine, 1, # SNMPv2c对应的mpModel值 'public', # 社区字符串 'my-area' # 安全名称标识 ) # 注册默认上下文(SNMPv2c默认使用空字符串作为上下文名称) snmpContext = context.SnmpContext(snmpEngine) snmpContext.registerContextName(v2c.OctetString(), process_snmp_request) # 配置UDP传输,监听127.0.0.1:1161 config.addTransport( snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('127.0.0.1', 1161)) ) print("SNMP Agent已启动,监听127.0.0.1:1161...") snmpEngine.transportDispatcher.jobStarted(1) try: snmpEngine.transportDispatcher.runDispatcher() except: snmpEngine.transportDispatcher.closeDispatcher() raise if __name__ == "__main__": create_snmp_agent()
问题根源分析
原代码存在两个致命问题:
- 社区字符串未正确配置:
原代码直接将CommunityData传给GetCommandResponder,但PySNMP需要通过config.addCommunity显式配置社区字符串,否则Agent会忽略所有未授权的请求。 - 上下文名称不匹配:
原代码注册了名为public的上下文,但SNMPv2c协议默认使用空字符串作为上下文名称,导致请求无法匹配到处理器,自然不会返回响应。
验证步骤
- 启动修复后的Agent:
python3 my_snmp-agent.py - 执行测试命令:
snmpget -v2c -c public 127.0.0.1:1161 1.3.6.1.4.1.9999.1 - 预期输出示例:
MY-MIB::memoryUtil = INTEGER: 38
额外优化说明
- 将OID前缀匹配改为精确匹配,避免误判;
- 对未知OID返回
noSuchInstance标准错误,符合SNMP协议规范; - 明确标注SNMPv2c对应的
mpModel值(1对应SNMPv2c)。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

