#!/usr/bin/env python # Copyright (c) 2015, 2024 Samuel Thibault # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY Samuel Thibault ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL Samuel Thibault BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. import sys import time import curses scr = curses.initscr() curses.noecho() curses.cbreak() scr.keypad(True) width = scr.getmaxyx()[1] - 1 netdev = open("/proc/net/dev") stats = {} newstats = {} oldtime = time.time() if sys.version_info[0] == 2: block = "\xe2\x96\x88" else: block = "\u2588" units = { 1 : "", 1000 : "K", 1000000 : "M", 1000000000 : "G", 1000000000000 : "T", 1000000000000000 : "P", 1000000000000000000 : "E", 1000000000000000000000 : "Z", 1000000000000000000000000 : "Y", 1000000000000000000000000000 : "R", 1000000000000000000000000000000 : "Q", } decade = 1 while True: netdev.seek(0) head1 = netdev.readline() head2 = netdev.readline() newtime = time.time() delta = newtime - oldtime newstats = {} while True: s = netdev.readline() if s == '': break iface,rest = s.split(':',2) iface = iface.strip() numbers = [ int(x) for x in rest.split(' ') if x != ''] newstats[iface] = { "RX_bytes" : numbers[0], "RX_packets" : numbers[1], "RX_errors" : numbers[2], "RX_drop" : numbers[3], "TX_bytes" : numbers[8], "TX_packets" : numbers[9], "TX_errors" : numbers[10], "TX_drop" : numbers[11], } if len(sys.argv) > 1: l = [ x for x in sys.argv[1:] if x in newstats and x in stats ] else: l = [ x for x in newstats if x in stats ] maxunit = 1 maxdecade = 1 for i in l: ns = newstats[i] s = stats[i] RX_BW = (ns["RX_bytes"] - s["RX_bytes"]) / delta while RX_BW >= maxunit * 1000: maxunit *= 1000 while RX_BW > maxdecade: maxdecade *= 10 TX_BW = (ns["TX_bytes"] - s["TX_bytes"]) / delta while TX_BW >= maxunit * 1000: maxunit *= 1000 while TX_BW > maxdecade: maxdecade *= 10 while not maxunit in units: maxunit /= 1000 unit = units[maxunit] if decade < maxdecade: decade = maxdecade if decade > maxdecade * 10: decade = maxdecade * 10 scr.erase() for i in l: ns = newstats[i] s = stats[i] RX_BW = (ns["RX_bytes"] - s["RX_bytes"]) / delta RX_P = (ns["RX_packets"] - s["RX_packets"]) / delta RX_E = (ns["RX_errors"] - s["RX_errors"]) / delta RX_D = (ns["RX_drop"] - s["RX_drop"]) / delta TX_BW = (ns["TX_bytes"] - s["TX_bytes"]) / delta TX_P = (ns["TX_packets"] - s["TX_packets"]) / delta TX_E = (ns["TX_errors"] - s["TX_errors"]) / delta TX_D = (ns["TX_drop"] - s["TX_drop"]) / delta scr.addstr("%-10s"%i + " RX % 5.1f%sB/s %2.0fp/s %2.0fE/s %2.0fD/s" % (RX_BW / maxunit, unit, RX_P, RX_E, RX_D) + " TX % 5.1f%sB/s %2.0fp/s %2.0fE/s %2.0fD/s" % (TX_BW / maxunit, unit, TX_P, TX_E, TX_D) + "\n") RX_b = int(RX_BW / decade * width) scr.addstr(block * RX_b + " " * (width-RX_b) + "\n") TX_b = int(TX_BW / decade * width) scr.addstr(block * TX_b + " " * (width-TX_b) + "\n") stats = newstats oldtime = newtime scr.refresh() scr.scrollok(1) time.sleep(1) curses.nocbreak() scr.keypad(False) curses.echo() curses.endwin()