1

我想在 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
)
4

2 回答 2

1

pysnmp 有一个补丁,可以让它与 eventlet 一起运行:

https://bitbucket.org/flub/pysnmp_eventlet

于 2013-09-30T06:38:49.587 回答
1

在上面的代码中,您仍然需要运行 eventlet 的调度程序来处理传入的数据包:

while True:
    eventlet.sleep(dispatcher.getTimerResolution())
    try:
        dispatcher.handleTimerTick(time.time())
    except Exception:
        print 'Error while handling dispatcher tick!'
        raise

您通常会在 greenlet 中生成它并忘记它(或者可能为它实施一些有序的关闭)。

(我将在未来某个时候向 pysnmp_eventlet 添加适当的示例。)

于 2013-10-28T22:33:38.983 回答