python工具---snmp流量监控,自定义粒度,业务突发可视化

个人博客地址

http://www.darkghost.life

现在主流监控软件和云平台提供的流量监控,监控粒度最小只能设置为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

 

posted @ 2021-07-02 20:02  无限's-blog  阅读(945)  评论(0编辑  收藏  举报