snmpgetをつかって定期的にそこのインターフェースに流れてるトラフィック量を表示する
というのをつくってみた。Internet Week 2009のこのBOFで紹介されてたのの劣化版ともいう。
#!/usr/bin/python #-*- coding: utf-8 -*- # # snmpgetをつかって定期的にカウンタの値をとってきて表示する # ターゲットはCSVファイルで指定 # import sys import csv import re import optparse import subprocess import select # コマンドラインオプションを解析する def parse_options(): parser = optparse.OptionParser() parser.add_option("-c", "--snmpget", dest="snmpget", default="/usr/bin/snmpget", help="snmpget path", type="string", action="store") parser.add_option("-f", "--file", dest="filename", default="iflist.csv", help="config file", type="string", action="store") parser.add_option("-i", "--interval", dest="interval", default=10, help="snmpget interval(sec)", type="int", action="store") (options, args) = parser.parse_args() csvfile = options.filename interval = options.interval snmpget = options.snmpget return (csvfile, interval, snmpget) # 設定ファイル=CSVファイルを読む # 設定ファイルのフォーマットは下記のとおり # ターゲットのIPアドレス,コミュニティ名,OID,表示名,SNMPバージョン def read_config(csvfile): iflist = [] reader = csv.reader(file(csvfile, "rb")) for row in reader: (ipaddress, community, oid, description, version) = row iflist.append({ 'ipaddress' : ipaddress, 'community' : community, 'oid' : oid, 'description' : description, 'version' : version, 'oldvalue' : 0 # snmpget's old value }) return iflist # タイムアウトつきreadline # http://funini.com/kei/py/select.shtml def readline_timeout(fd, timeout): (r, w, e) = select.select([fd], [], [], timeout) if len(r) > 0: return r[0].readline() else: return None # snmpgetコマンドで定期的にとってきて表示 def report(snmpget, iflist, interval): endflag = False while not endflag: for line in iflist: # subprocess.Popen()を使ってsnmpgetを実行する snmp = subprocess.Popen(["%s -v %s -c %s %s %s" % (snmpget, line['version'], line['community'], line['ipaddress'], line['oid'])], shell=True, stdout=subprocess.PIPE) # snmpgetコマンドの出力結果を取得する l = snmp.stdout.readline() m = re.match('^\S+ = (\S+): (\d+)$', l) (valuetype, valuestring) = m.groups() snmp.wait() # 取得したカウンタの種類によって、補正に使う値を決める # countermax : 64bit : 2^64 32bit : 2^32 if valuetype == 'Counter32': countermax = 2 ** 32 elif valuetype == 'Counter64': countermax = 2 ** 64 else: # 今のところCounter32とCounter64のみ対応とするので、 # それ以外は落ちてもらいます assert False value = int(valuestring) # カウンタがオーバーフローしてたら補正 if value < line['oldvalue']: v = value + countermax else: v = value traffic = (v - line['oldvalue']) * 8.0 / interval # コマンド実行直後だったら表示しない if line['oldvalue'] == 0: line['oldvalue'] = value continue else: line['oldvalue'] = value # トラフィック量に応じて単位を調整して表示 if traffic > 1000.0 * 1000.0 * 1000.0 : # over 1Gbps print "%s : %f Gbps" % (line['description'], traffic / 1000.0 / 1000.0 / 1000.0) elif traffic > 1000.0 * 1000.0 : # over 1Mbps print "%s : %f Mbps" % (line['description'], traffic / 1000.0 / 1000.0) elif traffic > 1000.0 : # over 1kbps print "%s : %f kbps" % (line['description'], traffic / 1000.0 ) else: # under 1kbps print "%s : %f bps" % (line['description'], traffic) # タイムアウトつきreadlineをつかって、 # なにか入力されたらおわりとして、 # なにも入力されなかったらループする s = readline_timeout(sys.stdin, interval) if s != None: endflag = True # メイン def main(): (csvfile, interval, snmpget) = parse_options() iflist = read_config(csvfile) report(snmpget, iflist, interval) if __name__ == '__main__': main()
ターゲットの情報はCSVファイルに書く。デフォルトは10秒平均。