PySNMP獲取設備信息


1.1. 快速入門

只要你在你的計算機上下載並安裝了 PySNMP 庫,你就可以解決非常基本的 SNMP 問題, 如通過 Python 命令行獲取某個遠程 SNMP Agent 的數據 (你至少需要 4.3.0 以上版本,才可以執行后面的示例代碼)。

1.1.1. 獲取 SNMP 變量

復制和粘貼下列代碼到 Python 命令提示符上,代碼將會執行 SNMP GET 操作獲取sysDescr.0對象,這是一個公開可用的 SNMP Command Responder,

"""
SNMPv1
++++++

Send SNMP GET request using the following options:

* with SNMPv1, community 'public'
* over IPv4/UDP
* to an Agent at demo.snmplabs.com:161
* for two instances of SNMPv2-MIB::sysDescr.0 MIB object,

Functionally similar to:

| $ snmpget -v1 -c public demo.snmplabs.com SNMPv2-MIB::sysDescr.0

"""#
from pysnmp.hlapi import *

errorIndication, errorStatus, errorIndex, varBinds = next(
  getCmd(SnmpEngine(),
          CommunityData('public', mpModel=0),
          UdpTransportTarget(('demo.snmplabs.com', 161)),
          ContextData(),
          ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
)

if errorIndication:
  print(errorIndication)
elif errorStatus:
  print('%s at %s' % (errorStatus.prettyPrint(),
                      errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
  for varBind in varBinds:
      print(' = '.join([x.prettyPrint() for x in varBind]))

如果一切執行正常,那么將會在你的終端打印:

...
SNMPv2-MIB::sysDescr."0" = SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m
>>>

1.1.2. 發送 SNMP TRAP

想給 demo.snmplabs.com 中列出的宿主 Notification Receiver 發送 TRAP 消息,復制以下代碼到你的交互式 Python 會話中。"""

SNMPv1 TRAP with defaults
+++++++++++++++++++++++++

Send SNMPv1 TRAP through unified SNMPv3 message processing framework
using the following options:

* SNMPv1
* with community name 'public'
* over IPv4/UDP
* send TRAP notification
* with Generic Trap #1 (warmStart) and Specific Trap 0
* with default Uptime
* with default Agent Address
* with Enterprise OID 1.3.6.1.4.1.20408.4.1.1.2
* include managed object information '1.3.6.1.2.1.1.1.0' = 'my system'

Functionally similar to:

| $ snmptrap -v1 -c public demo.snmplabs.com 1.3.6.1.4.1.20408.4.1.1.2 0.0.0.0 1 0 0 1.3.6.1.2.1.1.1.0 s "my system"

"""#
from pysnmp.hlapi import *

errorIndication, errorStatus, errorIndex, varBinds = next(
  sendNotification(
      SnmpEngine(),
      CommunityData('public', mpModel=0),
      UdpTransportTarget(('demo.snmplabs.com', 162)),
      ContextData(),
      'trap',
      NotificationType(
          ObjectIdentity('1.3.6.1.6.3.1.1.5.2')
      ).addVarBinds(
          ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'),
          ('1.3.6.1.2.1.1.1.0', OctetString('my system'))
      )
  )
)

if errorIndication:
  print(errorIndication)

PySNMP 獲取設備信息示例

2.1. cpu 信息 

根據 UCD-SNMP-MIB 文件,可以獲取的 cpu 參數共有 33 條,這里我們主要關注的是 cpu 的使用率,ssCpuIdle獲取的是 cpu 的空閑率,所以 100 - ssCpuIdle 既可以求得 cpu 的使用率。

def getCpuUsage(targetHost, targetPort, cmd, community):
    errIndication, errStatus, errIndex, varBindTable = cmd.nextCmd(
        cmdgen.CommunityData(community, mpModel=1),     # mpModel=1,表示使用v2協議
        cmdgen.UdpTransportTarget((targetHost,targetPort)), # 設備ip及端口
        cmdgen.MibVariable('UCD-SNMP-MIB','ssCpuIdle'),  # 需要訪問信息的MIB庫及子節點,也可以用形如'1.3.6.1.4'(OID標識符)的方式來定義
        #lookupValues=True
    )
    if errIndication:
        print errIndication
    else:
        if errStatus:
            print '%s at %s' % (
                errStatus.prettyPrint(),
                errIndex and varBindTable[-1][int(errIndex)-1] or '?'
                )
        else:
            return 100.0 - float(varBindTable[0][0][1].prettyPrint())

這是運行結果:

[[ObjectType(ObjectIdentity(ObjectName('1.3.6.1.4.1.2021.11.11.0')), Integer32(92))]]
CPU使用率:8.0

2.2. 內存信息 

可以獲取的完整內存對象信息也在http://mibs.snmplabs.com/asn1/UCD-SNMP-MIB上,包括 memTotalFree,memShared,memBuffer 等。

def getMemUsage(targetHost, targetPort, cmd, community):
    errIndication, errStatus, errIndex, varBindTable = cmd.nextCmd(
        cmdgen.CommunityData(community, mpModel=1),
        cmdgen.UdpTransportTarget((targetHost,targetPort)),
        cmdgen.MibVariable('UCD-SNMP-MIB','memTotalReal'), #'1.3.6.1.4.1.2021.4.5',
        cmdgen.MibVariable('UCD-SNMP-MIB','memAvailReal'), #'1.3.6.1.4.1.2021.4.6',
        cmdgen.MibVariable('UCD-SNMP-MIB','memBuffer'), #'1.3.6.1.4.1.2021.4.14',
        cmdgen.MibVariable('UCD-SNMP-MIB','memCached'), # '1.3.6.1.4.1.2021.4.15',
        #cmdgen.MibVariable('UCD-SNMP-MIB', 'memTotalSwap'),
        #lookupValues=True
        #lookupNames=True
    )
    #print varBindTable
    if errIndication:
        print errIndication
    else:
        if errStatus:
            print '%s at %s' % (
                errStatus.prettyPrint(),
                errIndex and varBindTable[-1][int(errIndex)-1] or '?'
                )
        else:
            mysum = 0.0
            totalAvailReal = float(varBindTable[0][0][1].prettyPrint())
            for var in varBindTable:
                for name , val in var:
                    mysum += float(val.prettyPrint())
            return totalAvailReal, (2*totalAvailReal - mysum) / totalAvailReal * 100.0

其中,比較重要的內存信息有:內存總量,緩沖區大小,cache 區大小,swap 區大小等。據此,可以計算出內存的使用率。

2.3. disk 信息 

disk 的相關信息也定義在 mib 文件 UCD-SNMP-MIB 中,根據該文件,可以獲取以下 disk 信息:

DskEntry ::= SEQUENCE {
    dskIndex        Integer32,
    dskPath     DisplayString,
    dskDevice       DisplayString,
    dskMinimum      Integer32,
    dskMinPercent   Integer32,
    dskTotal        Integer32,
    dskAvail        Integer32,
    dskUsed     Integer32,
    dskPercent      Integer32,
    dskPercentNode  Integer32,
    dskErrorFlag    UCDErrorFlag,
    dskErrorMsg     DisplayString,
    dskTotalLow     Unsigned32,
    dskTotalHigh    Unsigned32,
    dskAvailLow     Unsigned32,
    dskAvailHigh    Unsigned32,
    dskUsedLow      Unsigned32,
    dskUsedHigh     Unsigned32
}

根據 oid name,可以很容易看出其意思,下面的代碼可以用來獲取 disk 的使用信息:

def getDiskUsage(targetHost, targetPort, cmd, community):
    errIndication, errStatus, errIndex, varBindTable = cmd.nextCmd(
        cmdgen.CommunityData(community, mpModel=1),
        cmdgen.UdpTransportTarget((targetHost,targetPort)),
        cmdgen.MibVariable('UCD-SNMP-MIB', 'dskPath'), # '1.3.6.1.4.1.2021.9.1.2'
        cmdgen.MibVariable('UCD-SNMP-MIB', 'dskTotal'), # '1.3.6.1.4.1.2021.9.1.6'
        cmdgen.MibVariable('UCD-SNMP-MIB', 'dskPercent'), #'1.3.6.1.4.1.2021.9.1.9'
        cmdgen.MibVariable('UCD-SNMP-MIB', 'dskDevice'), #'1.3.6.1.4.1.2021.9.1.3'
        #lookupValues=True,
        #lookupNames=True
    )
    if errIndication:
        print errIndication

    else:
        if errStatus:
            print '%s at %s' % (errStatus.prettyPrint(), errIndex \
            and varBindTable[-1][int(errIndex)-1] or '?')
        else:
            result = []
            for var in varBindTable:
                tempResult = {}
                for name , val in var:
                    tempResult[name.getLabel()[len(name.getLabel())-1]] = val.prettyPrint()
                result.append(tempResult)
            return result

測試時,我們獲取到 waf 設備 10.11.113.150 的 disk 信息為空,其他設備可以正常獲取。

2.4. 流量信息 

也網卡或者流量相關的對象定義定義在 IF-MIB 中,可以獲取的具體信息包括:

IfEntry ::=
   SEQUENCE {
       ifIndex                 InterfaceIndex,
       ifDescr                 DisplayString,
       ifType                  IANAifType,
       ifMtu                   Integer32,
       ifSpeed                 Gauge32,
       ifPhysAddress           PhysAddress,
       ifAdminStatus           INTEGER,
       ifOperStatus            INTEGER,
       ifLastChange            TimeTicks,
       ifInOctets              Counter32,
       ifInUcastPkts           Counter32,
       ifInNUcastPkts          Counter32,  -- deprecated
       ifInDiscards            Counter32,
       ifInErrors              Counter32,
       ifInUnknownProtos       Counter32,
       ifOutOctets             Counter32,
       ifOutUcastPkts          Counter32,
       ifOutNUcastPkts         Counter32,  -- deprecated
       ifOutDiscards           Counter32,
       ifOutErrors             Counter32,
       ifOutQLen               Gauge32,    -- deprecated
       ifSpecific              OBJECT IDENTIFIER -- deprecated   }

以下是獲取網卡流量相關信息的示例代碼:

def getIfaceTraffic(targetHost, targetPort, cmd, community, period):
    def getNowTraffic():
        errIndication, errStatus, errIndex, varBindTable = cmd.nextCmd(
            cmdgen.CommunityData(community, mpModel=1),
            cmdgen.UdpTransportTarget((targetHost,targetPort)),
            cmdgen.MibVariable('IF-MIB', 'ifDescr'), # '1.3.6.1.2.1.2.2.1.2'
            cmdgen.MibVariable('IF-MIB', 'ifInOctets'), # '1.3.6.1.2.1.2.2.1.10'
            cmdgen.MibVariable('IF-MIB', 'ifOutOctets'), #'1.3.6.1.2.1.2.2.1.16'
            #lookupValues=True,
            #lookupNames=True
        )
        if errIndication:
            print errIndication

        else:
            if errStatus:
                print '%s at %s' % (errStatus.prettyPrint(), errIndex \
                and varBindTable[-1][int(errIndex)-1] or '?')
            else:
                result = []
                #print varBindTable
                for var in varBindTable:
                    tempResult = {}
                    for name , val in var:
                        tempResult[name.getLabel()[len(name.getLabel())-1]] = val.prettyPrint()
                    result.append(tempResult)
                return result

    preTraffic = getNowTraffic()
    #print preTraffic
    time.sleep(period)
    afterTraffic = getNowTraffic()
    #print afterTraffic

    traffic = []
    if(len(preTraffic) != len(afterTraffic)):
        return None
    else:
        ifaceNum = len(preTraffic)
    for i in range(ifaceNum):
        if preTraffic[i]['ifDescr'] == afterTraffic[i]['ifDescr']:
            m = float(preTraffic[i]['ifInOctets'])
            mm = float(afterTraffic[i]['ifInOctets'])
            n = float(preTraffic[i]['ifOutOctets'])
            nn = float(afterTraffic[i]['ifOutOctets'])
            ifaceName = preTraffic[i]['ifDescr']
            traffic.append({
                'ifaceName':ifaceName,
                'inTraffic(Mbps)':(mm-m)/period/1048576*8,
                'outTraffic(Mbps)':(nn-n)/period/1048576*8
            })
        else:
            return None
    return traffic

 




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM