开发snmp rddtools

 1  安装  /usr/ports/net-mgmt/net-snmp/   获取  snmpwalk 等管理调试命令    记得同时选上  支持 python 模块



2.  最近嘗試安裝bsnmp-ucd這個套件,但是安裝完後。 
也已經在/etc/snmpd.config中加入了: 
begemotSnmpdModulePath."ucd" = "/usr/local/lib/snmp_ucd.so" 

或查看了網路上其他方法,例如把某個UCD-SNMP-MIB.txt放到/usr/share/snmp/mibs裡面。或是snmp_ucd的conf範本檔貼進/etc/snmpd.config中等方式, 
restart完bsnmpd都沒有錯誤訊息,但就是撈不到CPU/memory等資料。 


3. 

snmpwalk -v 2c -c public localhost


4. 安装  rrdtool 

5   安装   py  rrd  包。:  python setup install 


6. 安装 py-setuptools


7 安装  Pyrrd   

python setup.py install 



这时应该会出来好多好多信息

 --------------------------------------------------

以下是Linux下一些常用的OID 

CPU的 

Load 
1 minute Load: .1.3.6.1.4.1.2021.10.1.3.1 
5 minute Load: .1.3.6.1.4.1.2021.10.1.3.2 
15 minute Load: .1.3.6.1.4.1.2021.10.1.3.3 

CPU 
percentage of user CPU time: .1.3.6.1.4.1.2021.11.9.0 
raw user cpu time: .1.3.6.1.4.1.2021.11.50.0 
percentages of system CPU time: .1.3.6.1.4.1.2021.11.10.0 
raw system cpu time: .1.3.6.1.4.1.2021.11.52.0 
percentages of idle CPU time: .1.3.6.1.4.1.2021.11.11.0 
raw idle cpu time: .1.3.6.1.4.1.2021.11.53.0 
raw nice cpu time: .1.3.6.1.4.1.2021.11.51.0 

-------------------------------------------------------------------------------

内存的 

Total Swap Size: .1.3.6.1.4.1.2021.4.3.0 
Available Swap Space: .1.3.6.1.4.1.2021.4.4.0 
Total RAM in machine: .1.3.6.1.4.1.2021.4.5.0 
Total RAM used: .1.3.6.1.4.1.2021.4.6.0 
Total RAM Free: .1.3.6.1.4.1.2021.4.11.0 
Total RAM Shared: .1.3.6.1.4.1.2021.4.13.0 
Total RAM Buffered: .1.3.6.1.4.1.2021.4.14.0 

Total Cached Memory: .1.3.6.1.4.1.2021.4.15.0 

-------------------------------------------------------------------

硬盘的

The snmpd.conf needs to be edited. Add the following (assuming a machine with a single ‘/’ partition): 

disk / 100000 (or) 

includeAllDisks 10% for all partitions and disks 

The OIDs are as follows 

Path where the disk is mounted: .1.3.6.1.4.1.2021.9.1.2.1 
Path of the device for the partition: .1.3.6.1.4.1.2021.9.1.3.1 
Total size of the disk/partion (kBytes): .1.3.6.1.4.1.2021.9.1.6.1 
Available space on the disk: .1.3.6.1.4.1.2021.9.1.7.1 
Used space on the disk: .1.3.6.1.4.1.2021.9.1.8.1 
Percentage of space used on disk: .1.3.6.1.4.1.2021.9.1.9.1 

Percentage of inodes used on disk: .1.3.6.1.4.1.2021.9.1.10.1 


----------------------------------------------------------------

以下是windows下常用的OID

CPU

.1.3.6.1.2.1.25.3.3.1.2

如果有一个双核cpu则有2个值,显示当前负载


内存,硬盘

内存跟硬盘都统一在mib2.host.hrStorage里 1.3.6.1.2.1.25.2

hrStorageType节点,hrStorageFixedDisk表示硬盘,hrStorageVirtualMemory是虚拟内存,hrStorageRam是内存

根据id号查:

hrStorageAllocationUnits是簇的大小

hrStorageSize是有多少簇,两者想乘就是总容量

hrStorageUsed是已使用多少,跟总容量相除就是占用率


---------------------------------------------------------------


系统运行时间

System Uptime: .1.3.6.1.2.1.1.3.0 

注:linux系统的话也可直接用uptime命令获得


网络设备的

ifIndex         1.3.6.1.2.1.2.2.1.1.0        端口索引号

ifDescr        1.3.6.1.2.1.2.2.1.2.0        端口描述

ifType        1.3.6.1.2.1.2.2.1.3.0        端口类型

ifMtu        1.3.6.1.2.1.2.2.1.4.0         最大传输包字节数

ifSpeed        1.3.6.1.2.1.2.2.1.5.0         端口速度

ifPhysAddress        1.3.6.1.2.1.2.2.1.6.0        物理地址

ifOperStatus        1.3.6.1.2.1.2.2.1.8.0        操作状态

ifLastChange        1.3.6.1.2.1.2.2.1.9.0        上次状态更新时间

ifInOctets        1.3.6.1.2.1.2.2.1.10.0         输入字节数

ifInUcastPkts        1.3.6.1.2.1.2.2.1.11.0         输入非广播包数

ifInNUcastPkts        1.3.6.1.2.1.2.2.1.12.0         输入广播包数

ifInDiscards        1.3.6.1.2.1.2.2.1.13.0         输入包丢弃数

ifInErrors        1.3.6.1.2.1.2.2.1.14.0         输入包错误数

ifInUnknownProtos        1.3.6.1.2.1.2.2.1.15.0        输入未知协议包数

ifOutOctets        1.3.6.1.2.1.2.2.1.16.0         输出字节数

ifOutUcastPkts        1.3.6.1.2.1.2.2.1.17.0         输出非广播包数

ifOutNUcastPkts        1.3.6.1.2.1.2.2.1.18.0        输出广播包数

ifOutDiscards        1.3.6.1.2.1.2.2.1.19.0         输出包丢弃数

ifOutErrors         1.3.6.1.2.1.2.2.1.20.0         输出包错误数

ifOutQLen        1.3.6.1.2.1.2.2.1.21.0         输出队长


流量输出的是计数器,单位是byte,32位

如果流量过大出现统计不正确的情况,就需要编译时加上enable-mfd-rewrites参数,来支持64位的计数器


Python Get示例:

单个get:

print "Get ntpClientEnabled"

oid = netsnmp.Varbind('1.3.6.1.4.1','2544.1.12.2.1.10.1.0')

oidList = netsnmp.VarList(oid)

resultList = netsnmp.snmpget(oid ,Version=2,DestHost='172.23.192.44',Community='private')

print resultList

 

以下是通过类的方法进行Get:

 

session = netsnmp.Session(Version=2,DestHost='172.23.192.44',Community='private')

oid = netsnmp.Varbind('1.3.6.1.4.1','2544.1.12.2.1.10.1.0',2,'INTEGER')

oidList = netsnmp.VarList(oid)

resultList = session.get(oidList)

print resultList         

 

多个get:

print "Get ntpClientEnabled"

oid = netsnmp.Varbind('1.3.6.1.4.1','2544.1.12.2.1.10.1.0')

oid1 =  netsnmp.Varbind('1.3.6.1.4.1.2544.1.12.8.1.1.1.5','1.1.1.1','15','INTEGER')

resultList = netsnmp.snmpget(oid ,oid1,Version=2,DestHost='172.23.192.44',Community='private')

print resultList

 

以下是通过类的方法进行Get

session = netsnmp.Session(Version=2,DestHost='172.23.192.44',Community='private')

oid2 = netsnmp.Varbind('1.3.6.1.4.1','2544.1.12.2.1.10.1.0',2,'INTEGER')

oid3 = netsnmp.Varbind('.1.3.6.1.4.1.2544.1.12.8.1.1.1.5','1.1.1.1',20,'INTEGER')

oidList = netsnmp.VarList(oid3,oid2)

resultList = session.get(oidList)

print resultList

 

注意类和函数的方式的区别。类方法始终要求传入的参数为oid列表,函数的方式则可以把单个或者多个oid作为参数传入,不需要oid列表。通过代码可以看到函数的方式其实调用类方法,为此,可能效率要比类方法低。

Python Set示例

 

调用netsnmp.snmpset一次set多个值:

print "Set ntpClientEnabled"

oid = netsnmp.Varbind('1.3.6.1.4.1.2544.1.12.2.1.10.1','0','2','INTEGER')

oid1 =  netsnmp.Varbind('1.3.6.1.4.1.2544.1.12.8.1.1.1.5','1.1.1.1','15','INTEGER')

resultList = netsnmp.snmpset(oid, oid1,Version=2,DestHost='172.23.192.44',Community='private')

print resultList

         上面的1.3.6.1.4.1.前面是否加点号没有关系。Varbind的init方法如下,tag可以用tid,比如ntpClientEnabled,iid表示后面带的序号,比如0,1.1.1.1。val表示具体的值,type表示类型,更详细的参见python netsnmp库的README。Val值'2'和'15'可以不加引号,以为这里是整型,建议还是全部加上引号。

         通过tcpdump抓包分析,snmpset多个值也发送了一次请求,因此多个set集合在一起发送,会明显提高效率。

class Varbind(object):

    def __init__(self, tag=None, iid=None, val=None, type=None):

        

         以下是通过类的方法进行set:

session = netsnmp.Session(Version=2,DestHost='172.23.192.44',Community='private')

oid2 = netsnmp.Varbind('1.3.6.1.4.1','2544.1.12.2.1.10.1.0',2,'INTEGER')

oid3 = netsnmp.Varbind('.1.3.6.1.4.1.2544.1.12.8.1.1.1.5','1.1.1.1',20,'INTEGER')

oidList = netsnmp.VarList(oid3,oid2)

resultList = session.set(oidList)

print resultList         

 

Mib翻译

通过snmptranslate -Tso >toid.txt可以导出tid和oid的对应表。

通过snmptranslate –Td 可以获取oid的详细定义。

# snmptranslate -Td .1.3.6.1.4.1.2544.1.12.2.1.10.1

CM-SYSTEM-MIB::ntpClientEnabled

ntpClientEnabled OBJECT-TYPE

  -- FROM       CM-SYSTEM-MIB

  -- TEXTUAL CONVENTION TruthValue

  SYNTAX        INTEGER {true(1), false(2)}

  MAX-ACCESS    read-write

  STATUS        current

  DESCRIPTION   "This allows to enable/disable the NTP client."

::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) advaMIB(2544) products(1) fsp150cm(12) cmSystemMIB(2) cmSystemObjects(1) cmTimeObjects(10) 1 }

为了提高可读性,我们需要在测试中使用true来表示1,false来表示2,并用ntpClientEnabled来表示.1.3.6.1.4.1.2544.1.12.2.1.10.1,遗憾的是,netsnmp的python库有如下限制“Access to the parsed MIB database is not yet implemented.”为此MIB的转换需要自行完成。为此拟定如下数据结构:

{ntpClientEnabled:.1.3.6.1.4.1.2544.1.12.2.1.10.1}

{ ntpClientEnabled:{ true:1, false:2}}

第2个字典只针对有别名的部分oid。

如果mib库不大,可以通过如下的脚本获取:

#!/usr/bin/python

# -*- coding: utf-8 -*-

# Function: Ssh to remote server

# Author:         Andrew Xu

# CreateDate: 2012/02/28

 

import subprocess

import re

import multiprocessing

import pickle

import time

import random

 

def producer(sequence, input_p):

    for item in sequence:

        # Put the item on the queue

        input_p.send(item)

 

# 消费者

def consumer(lock,pipe):

    output_p, input_p = pipe

    input_p.close() # 关闭管道输入口

    while True:

             lock.acquire()

             try:

                   time.sleep(1)

                   item = output_p.recv()

                   # 管道读取失败的预防,重试一次

             except Exception:

                   item = output_p.recv()

             lock.release()

             if item == None:

                   break

        

             tid = item

             oid = snmpDict[item]

        

             # 处理部分

             try:

                   result = subprocess.check_output(['snmptranslate', '-Td',oid])

                   # subprocess失败的预防,重试一次

             except Exception:

                   time.sleep(random.randint(1,8))

                   result = subprocess.check_output(['snmptranslate', '-Td',oid])

            

             syntaxLine = syntax.search(result)

             if  syntaxLine:               

                   syntaxLine = syntaxLine.group(1)       

                   valueitems = items.findall(syntaxLine)

                   snmpValueDict[tid] = dict(valueitems)         

             else:

                   lock.acquire()

                   print(tid,"None")

                   lock.release()            

                   continue

            

             lock.acquire()

             print(tid,dict(valueitems))

             lock.release()

       

   

 

if __name__ == '__main__':

   

    snmpDict = dict()

    snmpValueDict = dict()

    # 读取语法部分

    syntax = re.compile(r'^  SYNTAX.*?\{(.*?)\}',re.MULTILINE)

    # 读取字符串 和对应的值

    items = re.compile('(\w*)\((\w*)\)')

    f = open ("snmpValueDict.txt",'w')

   

    # 生成tid和oid对应的字典

    for line in open("tid_oid.txt"):

         tid, oid = line.strip().split(',')

         snmpDict[tid] = oid   

 

    pickle.dump(snmpValueDict, open("snmpTidOid.txt", "w"))     

        

    print "length of snmpDict:" + str(len(snmpDict))

   

    # 进程数、创建管道,锁等

    p_num = 10

    process = []   

    (output_p, input_p) = multiprocessing.Pipe()

    lock = multiprocessing.Lock()

   

    # 定义消费进程

    for i in range(p_num):

         t =multiprocessing.Process(target=consumer,args=(lock,(output_p, input_p),))     

         t.daemon=True

         process.append(t)   

 

    # 启动消费进程

    for i in range(p_num):

         process[i].start()

        

    # 关闭输出管道,以往管道填充数据

    output_p.close()

    sequence = snmpDict.values() + [None]*p_num

    producer(snmpDict.keys(), input_p)   

    # 数据填充完毕,打开输入管道

    input_p.close()

   

    # 等待结束

    for i in range(p_num):

         process[i].join()

   

    pickle.dump(snmpValueDict, open("snmpValueDict.txt", "w"))   

    print "length of snmpDict:" + str(len(snmpDict))   

    print "length of snmpValueDict:" + str(len(snmpValueDict))     

 

以上也是一个多进程程序的演示,如果mib的oid超过1000条,建议采用如下脚本来提取:

#!/usr/bin/python

# -*- coding: utf-8 -*-

# Function: Ssh to remote server

# Author:         Andrew Xu

# CreateDate: 2012/02/28

 

import re

import glob

import pickle

 

typeDict = dict()

snmpDict = dict()

snmpValueDict = dict()

 

# tid and oid dict

for line in open("tid_oid.txt"):

    tid, oid = line.strip().split(',')

    snmpDict[tid] = oid   

   

pickle.dump(snmpDict, open("snmpTidOid.txt", "w"))   

 

# type Dict

for mibFile in glob.glob(r"/home/share/andrew/soft/mib/110/MIBs/*.mib"):

    files = open(mibFile).read()

    text =re.sub("\s+"," ",files)

    result = re.findall(r'(\w*)\s+OBJECT-TYPE SYNTAX\s+\w+\s\{(.*?\(\w\).*?)\}',text)

 

    for dictName,values in result:

        splitValues = re.findall('(\w+)\s*?\((\w+)\)',values)

        typeDict[dictName] = dict(splitValues)

 

pickle.dump(snmpDict, open("typeDict.txt", "w"))               

 

# snmp Value Dict

for mibFile in glob.glob(r"D:\soft\mib\110\MIBs\*.mib"):

    print mibFile

    files = open(mibFile).read()

    text =re.sub("\s+"," ",files)

    result = re.findall(r'\s(\w*?) ::= TEXTUAL-CONVENTION STATUS current DESCRIPTION.*?SYNTAX\s+\w+\s\{(.*?\(\w\).*?)\}',text)

    print result   

    for dictName,values in result:

        splitValues = re.findall('(\w+)\s*?\((\w+)\)',values)

        snmpValueDict[dictName] = dict(splitValues)

       

    result = re.findall(r'\s(\w*?) ::= TEXTUAL-CONVENTION STATUS current DESCRIPTION.*?SYNTAX\s+\w+\s\{(.*?\(\w\).*?)\}',text)

 

pickle.dump(snmpValueDict, open("snmpValueDict.txt", "w"))   

 

上面的脚本需要根据mib文件格式的不同进行相应的调整。

现在就可以加载存储在文件中的字典,利用tid代替oid进行测试了。

 

#!/usr/bin/python

# -*- coding: utf-8 -*-

# Function: Ssh to remote server

# Author:         Andrew Xu

# CreateDate: 2012/02/28

 

 

import netsnmp

import re

import pickle

 

snmpTOidDict = pickle.load(open(r"snmpTidOid.txt"))

snmpValueDict = pickle.load(open(r"snmpValueDict.txt"))

 

print "Set ntpClientEnabled"

print snmpValueDict['ntpClientEnabled']

oid = netsnmp.Varbind(snmpTOidDict['ntpClientEnabled'], '0', snmpValueDict['ntpClientEnabled']['true'],'INTEGER')

oid1 =  netsnmp.Varbind(snmpTOidDict['ecpaControlDuration'],'1.1.1.1','15','INTEGER')

resultList = netsnmp.snmpset(oid, oid1,Version=2,DestHost='172.23.192.44',Community='private')

print resultList

 

下面搞个复杂点的用例,在某产品中创建和删除保护组:

命令行执行如下:

# snmpset -v2c -c private   172.23.192.44 cmFacProtGroupSwitchMode.1.1.1.1 i 1 cmFacProtGroupWorkPort.1.1.1.1 o 1.3.6.1.4.1.2544.1.12.4.1.7.1.1.1.1.1.1 cmFacProtGroupProtPort.1.1.1.1 o 1.3.6.1.4.1.2544.1.12.4.1.7.1.1.1.1.1.2 cmFacProtGroupRowStatus.1.1.1.1 i 4

 

CM-PROTECTION-MIB::cmFacProtGroupSwitchMode.1.1.1.1 = INTEGER: oneplusone(1)

CM-PROTECTION-MIB::cmFacProtGroupWorkPort.1.1.1.1 = OID: CM-FACILITY-MIB::cmEthernetNetPortIndex.1.1.1.1

CM-PROTECTION-MIB::cmFacProtGroupProtPort.1.1.1.1 = OID: CM-FACILITY-MIB::cmEthernetNetPortIndex.1.1.1.2

CM-PROTECTION-MIB::cmFacProtGroupRowStatus.1.1.1.1 = INTEGER: createAndGo(4)

 

# snmpset -v2c -c private  172.23.192.44 cmFacProtGroupRowStatus.1.1.1.1 i 6 CM-PROTECTION-MIB::cmFacProtGroupRowStatus.1.1.1.1 = INTEGER: destroy(6)

 

通过python实现如下

#!/usr/bin/python

# -*- coding: utf-8 -*-

# Function: Ssh to remote server

# Author:         Andrew Xu

# CreateDate: 2012/02/28

 

import netsnmp

import re

import pickle

 

snmpTOidDict = pickle.load(open(r"snmpTidOid.txt"))

snmpValueDict = pickle.load(open(r"snmpValueDict.txt"))

 

print  snmpValueDict['cmFacProtGroupRowStatus']

 

oid = netsnmp.Varbind(snmpTOidDict['cmFacProtGroupSwitchMode'], '1.1.1.1',

                      snmpValueDict['cmFacProtGroupSwitchMode']['oneplusone'],'INTEGER')

oid1 = netsnmp.Varbind(snmpTOidDict['cmFacProtGroupWorkPort'], '1.1.1.1',

                      snmpTOidDict['cmEthernetNetPortIndex'] + '.1.1.1.1','OBJECTID')

oid2 = netsnmp.Varbind(snmpTOidDict['cmFacProtGroupProtPort'], '1.1.1.1',

                      snmpTOidDict['cmEthernetNetPortIndex'] + '.1.1.1.2','OBJECTID')

oid3 = netsnmp.Varbind(snmpTOidDict['cmFacProtGroupRowStatus'], '1.1.1.1',

                      snmpValueDict['cmFacProtGroupRowStatus']['createAndGo'],'INTEGER')

 

resultList = netsnmp.snmpset(oid, oid1,oid2, oid3,Version=2,DestHost='172.23.192.44',Community='private')

print resultList

 

oid3 = netsnmp.Varbind(snmpTOidDict['cmFacProtGroupRowStatus'], '1.1.1.1',

                      snmpValueDict['cmFacProtGroupRowStatus']['destroy'],'INTEGER')

resultList = netsnmp.snmpset( oid3,Version=2,DestHost='172.23.192.44',Community='private')

print resultList

Normal 0 7.8 pt 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;}

当然上面这种调用方式,参数显得有点多,正式形成库时会再次封装。

 

性能

session = netsnmp.Session(Version=2,DestHost='172.23.192.44',Community='private')

oid = netsnmp.Varbind('1.3.6.1.4.1.2544.1.12','',2,'INTEGER')

oidList = netsnmp.VarList(oid)

resultList = session.walk(oidList)

print resultList         

print len(resultList)

 

通过上述代码,执行time ./test.py 。walk的效率:耗时:5m38.919s oid个数:13385

平均秒只能获取约40个oid。和参考资料中测试得5560 oids/sec有百倍左右的差距。不过我们的设备已经吃到近90%的cpu,这部分有待以后继续研究优化。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值