用python实现实时监控网卡流量(类似 top 动态刷新)

时间:2024-03-01 17:39:44

    很多时候,我们是需要查看服务器的网卡当前跑了多大流量,但对于网卡流量的查询,在linux下似乎没有像top那样的原生命令。虽然top功能很强大,可以实时查看cpu、内存、进程的动态,但是却没有对网卡流量的监控。既然没有,那那就自己写一个吧,哈哈。本文代码综合使用了psutil和curses模块,脚本工具同时支持在linux和windows下使用,支持动态查看网卡流量。当然现在也有些第三方的工具可以使用,比如iftop。

1.psutil模块   

    psutil可以获取系统的很多信息,包括CPU,内存,磁盘,网络,并且还可以查看系统进程等信息。psutil是一个跨平台的库,支持linux、windows、freebsd、OSX等多个操作系统平台。

2.curses模块

    curses库提供一个独立于终端的屏幕显示,支持各种控制代码来执行常见的操作,如移动光标、滚动屏幕和擦除区域。curses库将终端屏幕看成是由字符单元组成的坐标系,每一个单元由行坐标和列坐标来标示。坐标原点是屏幕的左上角,行坐标自上而下递增,列坐标自左而右递增。

3.实现思路 

  利用psutil获取到网卡的上传下载流量,计算出当前网卡的流量速率。然后利用curses将流量数据动态的输出到终端,实现top命令类似的动态刷新效果。

 

4.代码实现

  1 # -*- coding:utf-8 -*-
  2 
  3 """
  4 @Author: Rainbowhhy
  5 @Date: 2020-08-01 18:18:18
  6 """
  7 
  8 import psutil
  9 import time
 10 from datetime import datetime
 11 import curses
 12 import argparse
 13 
 14 
 15 def getNetworkData():
 16     # 获取网卡流量信息
 17     recv = {}
 18     sent = {}
 19     data = psutil.net_io_counters(pernic=True)
 20     interfaces = data.keys()
 21     for interface in interfaces:
 22         recv.setdefault(interface, data.get(interface).bytes_recv)
 23         sent.setdefault(interface, data.get(interface).bytes_sent)
 24     return interfaces, recv, sent
 25 
 26 
 27 def getNetworkRate(num):
 28     # 计算网卡流量速率
 29     interfaces, oldRecv, oldSent = getNetworkData()
 30     time.sleep(num)
 31     interfaces, newRecv, newSent = getNetworkData()
 32     networkIn = {}
 33     networkOut = {}
 34     for interface in interfaces:
 35         networkIn.setdefault(interface, float("%.3f" % ((newRecv.get(interface) - oldRecv.get(interface)) / num)))
 36         networkOut.setdefault(interface, float("%.3f" % ((newSent.get(interface) - oldSent.get(interface)) / num)))
 37     return interfaces, networkIn, networkOut
 38 
 39 
 40 def output(num, unit):
 41     # 将监控输出到终端
 42     stdscr = curses.initscr()
 43     curses.start_color()
 44     # curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
 45     curses.noecho()
 46     curses.cbreak()
 47     stdscr.clear()
 48     try:
 49         # 第一次初始化
 50         interfaces, _, _ = getNetworkData()
 51         currTime = datetime.now()
 52         timeStr = datetime.strftime(currTime, "%Y-%m-%d %H:%M:%S")
 53         stdscr.addstr(0, 0, timeStr)
 54         i = 1
 55         for interface in interfaces:
 56             if interface != "lo" and bool(1 - interface.startswith("veth")) and bool(
 57                     1 - interface.startswith("br")) and bool(
 58                 1 - interface.startswith("蓝牙")) and bool(1 - interface.startswith("VMware")):
 59                 if unit == "K" or unit == "k":
 60                     netIn = "%12.2fKB/s" % 0
 61                     netOut = "%11.2fKB/s" % 0
 62                 elif unit == "M" or unit == "m":
 63                     netIn = "%12.2fMB/s" % 0
 64                     netOut = "%11.2fMB/s" % 0
 65                 elif unit == "G" or unit == "g":
 66                     netIn = "%12.3fGB/s" % 0
 67                     netOut = "%11.3fGB/s" % 0
 68                 else:
 69                     netIn = "%12.1fB/s" % 0
 70                     netOut = "%11.1fB/s" % 0
 71                 stdscr.addstr(i, 0, interface)
 72                 stdscr.addstr(i + 1, 0, "Input:%s" % netIn)
 73                 stdscr.addstr(i + 2, 0, "Output:%s" % netOut)
 74                 stdscr.move(i + 3, 0)
 75                 i += 4
 76                 stdscr.refresh()
 77         # 第二次开始循环监控网卡流量
 78         while True:
 79             _, networkIn, networkOut = getNetworkRate(num)
 80             currTime = datetime.now()
 81             timeStr = datetime.strftime(currTime, "%Y-%m-%d %H:%M:%S")
 82             stdscr.erase()
 83             stdscr.addstr(0, 0, timeStr)
 84             i = 1
 85             for interface in interfaces:
 86                 if interface != "lo" and bool(1 - interface.startswith("veth")) and bool(
 87                         1 - interface.startswith("br")) and bool(
 88                     1 - interface.startswith("蓝牙")) and bool(1 - interface.startswith("VMware")):
 89                     if unit == "K" or unit == "k":
 90                         netIn = "%12.2fKB/s" % (networkIn.get(interface) / 1024)
 91                         netOut = "%11.2fKB/s" % (networkOut.get(interface) / 1024)
 92                     elif unit == "M" or unit == "m":
 93                         netIn = "%12.2fMB/s" % (networkIn.get(interface) / 1024 / 1024)
 94                         netOut = "%11.2fMB/s" % (networkOut.get(interface) / 1024 / 1024)
 95                     elif unit == "G" or unit == "g":
 96                         netIn = "%12.3fGB/s" % (networkIn.get(interface) / 1024 / 1024 / 1024)
 97                         netOut = "%11.3fGB/s" % (networkOut.get(interface) / 1024 / 1024 / 1024)
 98                     else:
 99                         netIn = "%12.1fB/s" % networkIn.get(interface)
100                         netOut = "%11.1fB/s" % networkOut.get(interface)
101                     stdscr.addstr(i, 0, interface)
102                     stdscr.addstr(i + 1, 0, "Input:%s" % netIn)
103                     stdscr.addstr(i + 2, 0, "Output:%s" % netOut)
104                     stdscr.move(i + 3, 0)
105                     i += 4
106                     stdscr.refresh()
107     except KeyboardInterrupt:
108         # 还原终端
109         curses.echo()
110         curses.nocbreak()
111         curses.endwin()
112     except Exception as e:
113         curses.echo()
114         curses.nocbreak()
115         curses.endwin()
116         print("ERROR: %s!" % e)
117         print("Please increase the terminal size!")
118     finally:
119         curses.echo()
120         curses.nocbreak()
121         curses.endwin()
122 
123 
124 if __name__ == "__main__":
125     parser = argparse.ArgumentParser(
126         description="A command for monitoring the traffic of network interface! Ctrl + C: exit")
127     parser.add_argument("-t", "--time", type=int, help="the interval time for ouput", default=1)
128     parser.add_argument("-u", "--unit", type=str, choices=["b", "B", "k", "K", "m", "M", "g", "G"],
129                         help="the unit for ouput", default="B")
130     parser.add_argument("-v", "--version", help="output version information and exit", action="store_true")
131     args = parser.parse_args()
132     if args.version:
133         print("v1.0")
134         exit(0)
135     num = args.time
136     unit = args.unit
137     output(num, unit)

 

5.用法说明

    1.仅支持python3。
    2.需安装psutil库,windows需安装curses库,linux默认自带,如果没有也需安装。
    3.支持指定刷新时间间隔,-t或者--time。
    4.支持指定流量输出单位,-u或者--unit。
    5.使用示例:
        (1)每5秒刷新一次数据,流量单位为M/s
            python3 network.py -t 5 -u M或者python3 network.py -t 5 -u m
        (2)默认不指定参数,表示每一秒刷新一次数据,流量单位为B/s
            python3 network.py

 

6.实现效果

linux下的效果

 

 

windows下的效果

 

号外

可以使用工具将脚本打包成二进制文件,之后可以像执行linux命令那样直接执行,无需安装依赖包。
networkstat下载
目前支持Ubuntu14.04以上,CentOS7以上,Debian8以上,Windows10,Windows2008R2以上。