我想在 python 中做一个 snmpget 而不会阻塞。我不想使用线程,我真的很喜欢 gevent 库,但我以前没有使用过它,所以不知道从哪里开始。我查看了他们的示例并了解了如何修补套接字。如果我猴子修补套接字并使用像 pysnmp 这样的模块,执行非阻塞查询就足够了吗?
此外,由于我将使用 linux 机器,因此我可以访问snmpget
命令行实用程序,因此我可以使用 1.0 版中提供的 gevent.subprocess 调用它们,这也可以使这些查询成为非阻塞的。
与使用命令行实用程序相比,我更喜欢使用 python 模块来执行 snmp get,但是如果第二个选项更容易开始工作,那么我不介意采用这种方法。
任何提示/方向将不胜感激。谢谢!
更新:
我采用了 pysnmp_eventlet 模块并尝试采用带有 eventlet 的 Twisted 示例。我不确定为什么我的回调函数没有被调用。我可以在 tcpdump 中看到 SNMP 请求和响应。但是我的回调函数(cbFun)没有被调用。我错过了什么吗?
from pysnmp_eventlet.carrier.eventlet.dispatch import EventletDispatcher
from pysnmp_eventlet.carrier.eventlet.dgram import udp
from pysnmp.entity.rfc3413 import cmdgen
from pysnmp.entity import engine, config
# Create SNMP engine instance
snmpEngine = engine.SnmpEngine()
dispatcher = EventletDispatcher()
snmpEngine.registerTransportDispatcher(dispatcher)
# SecurityName <-> CommunityName mapping
config.addV1System(snmpEngine, 'my-area', 'public')
# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1)
# UDP/IPv4
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.UdpEventletTransport().openClientMode()
)
config.addTargetAddr(
snmpEngine,
'my-router',
udp.domainName,
('127.0.0.1', 161),
'my-creds',
timeout=300, # in 1/100 sec
retryCount=1
)
def cbFun(cbCtx):
(errorIndication, errorStatus, errorIndex, varBinds) = cbCtx
if errorIndication:
print(errorIndication)
elif errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
)
)
else:
for oid, val in varBinds:
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
cmdGen = cmdgen.GetCommandGenerator()
cmdGen.sendReq(
snmpEngine,
'my-router',
( ('1.3.6.1.2.1.1.1.0', None), ),
cbFun
)