1. 程式人生 > 實用技巧 >python實現系統公網和私網流量監控

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.輸出結果截圖

如下圖是輸出結果展示