刮掉多个单个和分支OID的最有效方法是什么?

时间:2015-10-20 13:00:16

标签: python cpu snmp pysnmp

我总是处于最大速度和最小资源消耗之间的战争,因此我的目标是找到速度和资源消耗的最佳组合。
对于每个snmp设备,我想扫描几个分支下的oid 每个分支都有动态数量的oid,所以我不知道我需要什么特定的oid,我只知道我需要一个分支下的所有oid。
我有一些设备只支持SNMPv1,所以对于那些设备,我编写了与SNMPv1兼容的代码 对于其他设备,我使用SNMPv2。

SNMPv1的

假设我有两个OID,我想走他们的branch('1.3.6.1.2.1.4' and '1.3.6.1.2.1.6') 分支OID是指分支下的所有OID 我有以下代码:

cmdGen = cmdgen.AsynCommandGenerator()
cmdGen.asyncNextCmd(
  cmdgen.CommunityData('public', mpModel=1),
  cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
  (str('1.3.6.1.2.1.4'),str('1.3.6.1.2.1.6'),),
  (__cbFun_Walk, (cmdgen.CommunityData('public', mpModel=1), cmdgen.UdpTransportTarget(('192.168.0.101', 161)))))
cmdGen.snmpEngine.transportDispatcher.runDispatcher()

这很有效,但唯一的问题是我只能一次性停止所有步行,因此我不能单独停止每次步行,所以一旦最长的步行结束,所有步行都将完成。
显然这是低效的 我还可以为分支OID编写2 asyncNextCmd

cmdGen = cmdgen.AsynCommandGenerator()
cmdGen.asyncNextCmd(
        cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
        (str('1.3.6.1.2.1.4'),),
        (__cbFun_Walk, (cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161))))) 
cmdGen.asyncNextCmd(
        cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
        (str('1.3.6.1.2.1.6'),),
        (__cbFun_Walk, (cmdgen.CommunityData('public', mpModel=1),
        cmdgen.UdpTransportTarget(('192.168.0.101', 161)))))
cmdGen.snmpEngine.transportDispatcher.runDispatcher()

我不太了解SNMP,但我认为第二个代码有一些缺点 例如,在某些客户端上,我有数百个SNMP设备,因此我同时为每个网络设备打开了asyncCmd 这导致了许多无响应的设备和过高的CPU使用率。

的SNMPv2

我还想尝试了解批量的工作方式,以及是否可以使用它来提高我的代码效率 可以说我有2个分支,我想走路 1.3.6.1.2.1.4.20有5个oids,1.3.6.1.2.1.4.21有39个oids。
我得到了两个分支中的所有值,但我也得到了更多的值,然后我也想要 我获得的值总是具有最高oid数量的分支乘以我拥有的分支数量 例如,具有最多oid的分支具有39个oid,并且分支的数量是2,因此39 * 2 = 78,这意味着getBulk将返回78个oid。 我希望getBulk返回每个分支的所有分支oid而不是更多,所以在我的情况下我想要44个oid(39 + 5 = 44)。
这是我的代码:

cmdGen = cmdgen.CommandGenerator()

errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.bulkCmd(
  cmdgen.CommunityData('public'),
  cmdgen.UdpTransportTarget(('192.168.0.101', 161)),
  0, 1,
  '1.3.6.1.2.1.4.21', '1.3.6.1.2.1.4.20'
)

if errorIndication:
  print errorIndication
elif errorStatus:
  print '%s at %s\n' % (
    errorStatus.prettyPrint(),
    errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
  )
else:
  for varBindTableRow in varBindTable:
    for name, val in varBindTableRow:
      print str(name.prettyPrint()) + ' = ' + str(val.prettyPrint())

那么为SNMPv1和SNMPv2抓取多个分支OID的最有效方法是什么?

2 个答案:

答案 0 :(得分:1)

首先要意识到的是,您无法指示SNMP代理返回正确的分支"。 SNMP(协议级别)不支持此类操作。管理者可以控制要求的OID和何时停止。代理可以一次返回确切的单个OID(GET)或下一个OID(GETNEXT / GETBULK)或下一个OID的大概数量(GETBULK)。

如果您有动态OID,则无法在任何给定时刻可靠地预测其中有多少OID。因此,我不认为您可以在单个SNMP操作中严格获得分支OID。

话虽如此,我认为你应尽可能尝试使用GETBULK。瞄准最大预期的OID数量,以便在一次GETBULK操作中获取它们。但请检查您的代码,确实可以获得所有内容(代理可能不会同时返回所请求的OID数量)。

对于您正在使用的pysnmp API,要停止其GETBULK / GETNEXT迭代,您应该从回调函数返回True。您可以分析从代理处获得的OID,并在超出您感兴趣的分支时返回True。这将终止一个分支检索,其余将继续运行。

为不同的OID发送多个并行查询到同一SNMP代理的设计效率明显低得多。

答案 1 :(得分:0)

您想要{/ 1}},如

所述

http://pysnmp.sourceforge.net/examples/current/v3arch/oneliner/manager/cmdgen/getbulk-v2c.html

它将以更少和更大的块从网络设备返回数据。