python实现系统公网和私网流量监控

    目前很多公司业务已经上云,使用了大量的云主机。当前大多数云厂商的云主机公网都是采用的eip,也就是内网和外网使用的同一张网卡,所以流量全部经过的同一个网卡。然而这就面临一个问题,如何将公网和私网的流量分开统计呢?特别是当机器流量异常的时候,如何快速的判断流量是来自公网还是私网。当然云厂商一般也提供了eip的监控,然而很多公司也有一套自己的监控,对于自建监控如何实现,这就值得思考了。
    本文将采用python实现云主机的公网和私网流量分开统计,可以将结果输入到自建监控中,当发生业务故障时,可以快速定位问题。

 

1. iftop

iftop是linux系统下面一个监控主机与外部通信的工具,它可以实时监控本机与外部机器的流量大小,需要自行下载安装包编译安装。iftop类似与linux系统自带的top命令,在屏幕终端动态输出监控结果。同时,iftop支持很多参数可选项,其中-t 参数使用不带ncurses的文本界面,可以实现将结果保存到文件。

 

2. os.popen函数

    os是python的系统模块,os.popen可以调用系统的shell命令,相当于直接在shell终端执行shell命令。

 

3. 实现思路

    使用python的os.open来调用iftop命令获取到和主机通信的所有ip的流量大小。然后分别分析公网和私网的流量,将各自的流量之和统计起来,从而实现分别监控系统的公网和私网流量。

 

4. 代码实现

 1 # -*- coding:utf-8 -*-
 2 """
 3 @Author: Rainbowhhy
 4 @Date: 2020-11-14 15:16:18
 5 """
 6 
 7 import os, re
 8 
 9 
10 def is_public_ip(ip):
11     # 判断ip是公网还是私网
12     private = re.findall(
13         r'^((192\.168)|(198\.18)|(198\.19)|(10\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))|(172\.(1[6-9]|2[0-9]|3[0-1])))\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$',
14         ip)
15     if private:
16         return 0
17     else:
18         return 1
19 
20 
21 def convert_unit(unit):
22     # 统一转换成bit后计算
23     if "Gb" in unit:
24         flow = float(unit.strip("Gb")) * 1024 * 1024 * 1024
25     elif "Mb" in unit:
26         flow = float(unit.strip("Mb")) * 1024 * 1024
27     elif "Kb" in unit:
28         flow = float(unit.strip("Kb")) * 1024
29     else:
30         flow = float(unit.strip("b"))
31     return flow
32 
33 
34 def get_traffic():
35     # 调用iftop命名获取公网和私网流量
36     iftop_info = os.popen("iftop -t -N -n -s 4 2>/dev/null | grep -A 1 -E '^   [0-9]'").read()
37     iftop_list = iftop_info.split("\n")
38     count = len(iftop_list) - 1
39     public_traffic_send = 0
40     public_traffic_recv = 0
41     private_traffic_send = 0
42     private_traffic_recv = 0
43     public_ips = []
44     private_ips = []
45     for i in range(int(count / 2)):
46         # 获取出向流量信息
47         traffic_send = iftop_list[i * 2]
48         traffic_send_lists = traffic_send.split(" ")
49         while "" in traffic_send_lists:
50             traffic_send_lists.remove("")
51         traffic_send = traffic_send_lists[3]
52         traffic_send_float = convert_unit(traffic_send)
53 
54         # 获取入向流量信息
55         traffic_recv = iftop_list[i * 2 + 1]
56         traffic_recv_lists = traffic_recv.split(" ")
57         while "" in traffic_recv_lists:
58             traffic_recv_lists.remove("")
59         ip = traffic_recv_lists[0]
60         traffic_recv = traffic_recv_lists[2]
61         traffic_recv_float = convert_unit(traffic_recv)
62 
63         # 计算公网和私网的总流量
64         if is_public_ip(ip):
65             public_ips.append(ip)
66             public_traffic_send += traffic_send_float
67             public_traffic_recv += traffic_recv_float
68 
69         else:
70             private_ips.append(ip)
71             private_traffic_send += traffic_send_float
72             private_traffic_recv += traffic_recv_float
73     return public_traffic_send, public_traffic_recv, private_traffic_send, private_traffic_recv
74 
75 
76 if __name__ == '__main__':
77     public_traffic_send, public_traffic_recv, private_traffic_send, private_traffic_recv = get_traffic()
78     print("公网入向:%.1f" % public_traffic_recv)
79     print("公网出向:%.1f" % public_traffic_send)
80     print("私网入向:%.1f" % private_traffic_recv)
81     print("私网出向:%.1f" % private_traffic_send)

 

5. 输出结果截图

如下图是输出结果展示

 

posted @ 2020-11-14 19:13  Rainbowhhy  阅读(667)  评论(0编辑  收藏  举报