python工具---snmp流量监控,自定义粒度,业务突发可视化
个人博客地址
现在主流监控软件和云平台提供的流量监控,监控粒度最小只能设置为1分钟,无法准确定位故障,特别是瞬时突发较大的业务
对比python的snmp库还是更喜欢用subprocess调用snmpwalk命令,脚本如下,前端可以使用脚本采集到的数据进行绘图
snmpwalk版本,系统需要安装 snmp snmp-mibs-downloader
1 #! /usr/bin/env python 2 #-*-coding:utf-8-*- 3 import time,subprocess,re,signal,os,sys 4 class traffic: 5 def __init__(self,ip,port,community,interval): 6 try: 7 cmd_index = 'snmpwalk -v 2c -c %s %s ifDescr | grep -w %s'%(community,ip,port) 8 print(cmd_index) 9 portindex = subprocess.Popen(cmd_index,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0] 10 print(portindex) 11 ret = re.findall('ifDescr.\d+',portindex.decode('utf8'))[0] 12 print(ret) 13 portMIB = int(re.findall('\d+',ret)[0]) 14 self.cmd_in='snmpwalk -v 2c -c %s %s ifHCInOctets.%s'%(community,ip,portMIB) 15 self.cmd_out='snmpwalk -v 2c -c %s %s ifHCOutOctets.%s'%(community,ip,portMIB) 16 self.interval = interval 17 except: 18 print('please check snmp and snmp-mibs-downloader') 19 print('-----------------examples-----------------------') 20 print('dpkg -l | grep snmp') 21 print('sudo > /etc/snmp/snmp.conf') 22 sys.exit(0) 23 def form(self,data): 24 ret = re.findall('Counter64:.*',data.decode('utf8'))[0] 25 ret = ret.split(':')[1].strip() 26 ret = round(int(ret)*8/1024/1024,2) 27 return ret 28 def snmp(self): 29 traffic_in = subprocess.Popen(self.cmd_in,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0] 30 traffic_out = subprocess.Popen(self.cmd_out,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0] 31 traffic_in = self.form(traffic_in) 32 traffic_out = self.form(traffic_out) 33 return(traffic_in,traffic_out) 34 def gettraffic(self): 35 befo_in,befo_out = self.snmp() 36 time.sleep(self.interval) 37 after_in,after_out = self.snmp() 38 return ({'in':round((after_in-befo_in)/self.interval,2),'out':round((after_out-befo_out)/self.interval,2)}) 39 def signal_handler(*args, **kwargs): 40 try: 41 if count!=0: 42 print('----------------------------end-----------------------------') 43 print(' min max avg') 44 print('incoming %sM %sM %sM'%(traffic_in_min,traffic_in_max,round(traffic_in_sum/count,2))) 45 print('outgoing %sM %sM %sM'%(traffic_out_min,traffic_out_max,round(traffic_out_sum/count,2))) 46 except: 47 os._exit(0) 48 os._exit(0) 49 if __name__ == "__main__": 50 signal.signal(signal.SIGINT, signal_handler) 51 traffic_in_max = 0 52 traffic_out_max = 0 53 traffic_in_min = 999999999999 54 traffic_out_min = 999999999999 55 traffic_in_sum = 0 56 traffic_out_sum = 0 57 count = 0 58 try: 59 host = sys.argv[1] 60 port = sys.argv[2] 61 community = sys.argv[3] 62 interval = int(sys.argv[4]) 63 mx =traffic(host,port,community,interval) 64 print('-------------%s %s秒粒度流量监控------------------'%(host,interval)) 65 while True: 66 ret = mx.gettraffic() 67 traffic_in = ret['in'] 68 traffic_out = ret['out'] 69 traffic_in_max = max(traffic_in,traffic_in_max) 70 traffic_out_max = max(traffic_out,traffic_out_max) 71 traffic_in_min = min(traffic_in,traffic_in_min) 72 traffic_out_min = min(traffic_out,traffic_out_min) 73 traffic_in_sum += traffic_in 74 traffic_out_sum += traffic_out 75 count+=1 76 print('traffic_in: %s Mbps'%traffic_in,'traffic_out: %s Mbps'%traffic_out) 77 except: 78 print('usage:') 79 print(' <host> <portMIB> <community> <interval>') 80 print('options:') 81 print(' host: <dest_ip>') 82 print(' portMIB <dest port>') 83 print(' community: <community>') 84 print(' interval: <get data interval>') 85 print('examples:') 86 print(' ./traffic 10.0.0.1 ge-0/0/46 public 5')
pysnmp版本 pip install pysnmp
1 from pysnmp.hlapi import * 2 import time,os,signal,sys 3 class port_traffic_index: 4 def __init__(self,community,host,port): 5 self.community = community 6 self.host = (host,161) 7 self.port=port 8 #获取接口数量 9 @property 10 def index_count(self): 11 iterator = getCmd(SnmpEngine(), 12 CommunityData(self.community), 13 UdpTransportTarget(self.host), 14 ContextData(), 15 ObjectType(ObjectIdentity('IF-MIB', 'ifNumber', 0))) 16 errorIndication, errorStatus, errorIndex, varBinds = next(iterator) 17 for varBind in varBinds: 18 mib,count=[x.prettyPrint() for x in varBind] 19 return int(count) 20 #获取接口对应的mib index值 21 def port_index(self): 22 port_count = self.index_count 23 N,R=0,1000 24 iterator = bulkCmd(SnmpEngine(), 25 CommunityData(self.community), 26 UdpTransportTarget(self.host), 27 ContextData(), 28 N,R, 29 ObjectType(ObjectIdentity('IF-MIB','ifDescr'))) 30 for x in range(port_count): 31 errorIndication, errorStatus, errorIndex, varBinds = next(iterator) 32 if errorIndication: # SNMP engine errors 33 print(errorIndication) 34 else: 35 if errorStatus: # SNMP agent errors 36 print('%s at %s' % (errorStatus.prettyPrint(), varBinds[int(errorIndex)-1] if errorIndex else '?')) 37 else: 38 for varBind in varBinds: # SNMP response contents 39 #接口mib与接口名称做为一个列表,分别赋值给mib,port 40 mib,port=[x.prettyPrint() for x in varBind] 41 if port == self.port: 42 mib1,mib_index=mib.split('.') 43 return int(mib_index) 44 #获取接口流量 45 def port_traffic(self,index): 46 iterator = getCmd(SnmpEngine(), 47 CommunityData(self.community), 48 UdpTransportTarget(self.host), 49 ContextData(), 50 ObjectType(ObjectIdentity('IF-MIB', 'ifHCInOctets', index)), 51 ObjectType(ObjectIdentity('IF-MIB', 'ifHCOutOctets', index))) 52 errorIndication, errorStatus, errorIndex, varBinds = next(iterator) 53 t_in,t_out = varBinds # SNMP response contents,有两个对象分别对应请求的mib 54 key_in,traffic_in=[x.prettyPrint() for x in t_in] 55 key_out,traffic_out=[x.prettyPrint() for x in t_out] 56 return int(traffic_in),int(traffic_out) 57 58 def get_traffic(self,port_index,interval): 59 inittraffic_in,inittraffic_out = self.port_traffic(port_index) 60 time.sleep(interval) 61 aftraffic_in,aftraffic_out = self.port_traffic(port_index) 62 traffic_in = round((aftraffic_in-inittraffic_in)*8/1024/1024/interval,2) 63 traffic_out = round((aftraffic_out-inittraffic_out)*8/1024/1024/interval,2) 64 return traffic_in,traffic_out 65 66 def signal_handler(*args, **kwargs): 67 try: 68 if count!=0: 69 print('----------------------------end-----------------------------') 70 print(' min max avg') 71 print('incoming %sM %sM %sM'%(traffic_in_min,traffic_in_max,round(traffic_in_sum/count,2))) 72 print('outgoing %sM %sM %sM'%(traffic_out_min,traffic_out_max,round(traffic_out_sum/count,2))) 73 except: 74 os._exit(0) 75 os._exit(0) 76 77 if __name__ == '__main__': 78 signal.signal(signal.SIGINT, signal_handler) 79 traffic_in_max = 0 80 traffic_out_max = 0 81 traffic_in_min = 999999999999 82 traffic_out_min = 999999999999 83 traffic_in_sum = 0 84 traffic_out_sum = 0 85 count = 0 86 try: 87 host = sys.argv[1] 88 port = sys.argv[2] 89 community = sys.argv[3] 90 interval = int(sys.argv[4]) 91 traffic = port_traffic_index(community, host, port) 92 port_index = traffic.port_index() 93 while True: 94 traffic_in,traffic_out = traffic.get_traffic(port_index, interval) 95 traffic_in_max = max(traffic_in,traffic_in_max) 96 traffic_out_max = max(traffic_out,traffic_out_max) 97 traffic_in_min = min(traffic_in,traffic_in_min) 98 traffic_out_min = min(traffic_out,traffic_out_min) 99 traffic_in_sum += traffic_in 100 traffic_out_sum += traffic_out 101 count+=1 102 print('traffic_in: %s Mbps'%traffic_in,'traffic_out: %s Mbps'%traffic_out) 103 except: 104 print('usage:') 105 print(' <host> <portMIB> <community> <interval>') 106 print('options:') 107 print(' host: <dest_ip>') 108 print(' portMIB <dest port>') 109 print(' community: <community>') 110 print(' interval: <get data interval>') 111 print('examples:') 112 print(' ./pytraffic 10.0.0.1 ge-0/0/46 public 5') 113 114 115
效果如下
1 $ ./traffic.py 2 usage: 3 <host> <port> <community> <interval> 4 options: 5 host: <dest_ip> 6 port <dest port> 7 community: <community> 8 interval: <get data interval> 9 examples: 10 ./traffic.py 10.0.0.1 ge-0/0/46 public 5 11 12 13 $ ./traffic.py 10.0.0.1 ge-0/0/46 public 5 14 -------------10.0.0.1 5秒粒度流量监控------------------ 15 traffic_in: 7.65 Mbps traffic_out: 42.16 Mbps 16 traffic_in: 14.98 Mbps traffic_out: 51.32 Mbps 17 traffic_in: 13.96 Mbps traffic_out: 51.99 Mbps 18 traffic_in: 8.18 Mbps traffic_out: 44.42 Mbps 19 traffic_in: 8.99 Mbps traffic_out: 53.03 Mbps 20 traffic_in: 17.66 Mbps traffic_out: 49.03 Mbps 21 traffic_in: 47.14 Mbps traffic_out: 49.27 Mbps 22 traffic_in: 71.05 Mbps traffic_out: 50.45 Mbps 23 traffic_in: 72.73 Mbps traffic_out: 48.16 Mbps 24 ^C----------------------------end----------------------------- 25 min max avg 26 incoming 7.65M 72.73M 29.15M 27 outgoing 42.16M 53.03M 48.87M
以驱魔为理想,为生计而奔波