nettop.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env python
  2. #
  3. # $Id: iotop.py 1160 2011-10-14 18:50:36Z g.rodola@gmail.com $
  4. #
  5. # Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
  6. # Use of this source code is governed by a BSD-style license that can be
  7. # found in the LICENSE file.
  8. """
  9. Shows real-time network statistics.
  10. Author: Giampaolo Rodola' <g.rodola@gmail.com>
  11. $ python examples/nettop.py
  12. -----------------------------------------------------------
  13. total bytes: sent: 1.49 G received: 4.82 G
  14. total packets: sent: 7338724 received: 8082712
  15. wlan0 TOTAL PER-SEC
  16. -----------------------------------------------------------
  17. bytes-sent 1.29 G 0.00 B/s
  18. bytes-recv 3.48 G 0.00 B/s
  19. pkts-sent 7221782 0
  20. pkts-recv 6753724 0
  21. eth1 TOTAL PER-SEC
  22. -----------------------------------------------------------
  23. bytes-sent 131.77 M 0.00 B/s
  24. bytes-recv 1.28 G 0.00 B/s
  25. pkts-sent 0 0
  26. pkts-recv 1214470 0
  27. """
  28. import atexit
  29. import time
  30. import sys
  31. try:
  32. import curses
  33. except ImportError:
  34. sys.exit('platform not supported')
  35. import psutil
  36. # --- curses stuff
  37. def tear_down():
  38. win.keypad(0)
  39. curses.nocbreak()
  40. curses.echo()
  41. curses.endwin()
  42. win = curses.initscr()
  43. atexit.register(tear_down)
  44. curses.endwin()
  45. lineno = 0
  46. def print_line(line, highlight=False):
  47. """A thin wrapper around curses's addstr()."""
  48. global lineno
  49. try:
  50. if highlight:
  51. line += " " * (win.getmaxyx()[1] - len(line))
  52. win.addstr(lineno, 0, line, curses.A_REVERSE)
  53. else:
  54. win.addstr(lineno, 0, line, 0)
  55. except curses.error:
  56. lineno = 0
  57. win.refresh()
  58. raise
  59. else:
  60. lineno += 1
  61. # --- curses stuff
  62. def bytes2human(n):
  63. """
  64. >>> bytes2human(10000)
  65. '9.8 K'
  66. >>> bytes2human(100001221)
  67. '95.4 M'
  68. """
  69. symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
  70. prefix = {}
  71. for i, s in enumerate(symbols):
  72. prefix[s] = 1 << (i + 1) * 10
  73. for s in reversed(symbols):
  74. if n >= prefix[s]:
  75. value = float(n) / prefix[s]
  76. return '%.2f %s' % (value, s)
  77. return '%.2f B' % (n)
  78. def poll(interval):
  79. """Retrieve raw stats within an interval window."""
  80. tot_before = psutil.net_io_counters()
  81. pnic_before = psutil.net_io_counters(pernic=True)
  82. # sleep some time
  83. time.sleep(interval)
  84. tot_after = psutil.net_io_counters()
  85. pnic_after = psutil.net_io_counters(pernic=True)
  86. return (tot_before, tot_after, pnic_before, pnic_after)
  87. def refresh_window(tot_before, tot_after, pnic_before, pnic_after):
  88. """Print stats on screen."""
  89. global lineno
  90. # totals
  91. print_line("total bytes: sent: %-10s received: %s" % (
  92. bytes2human(tot_after.bytes_sent),
  93. bytes2human(tot_after.bytes_recv))
  94. )
  95. print_line("total packets: sent: %-10s received: %s" % (
  96. tot_after.packets_sent, tot_after.packets_recv))
  97. # per-network interface details: let's sort network interfaces so
  98. # that the ones which generated more traffic are shown first
  99. print_line("")
  100. nic_names = list(pnic_after.keys())
  101. nic_names.sort(key=lambda x: sum(pnic_after[x]), reverse=True)
  102. for name in nic_names:
  103. stats_before = pnic_before[name]
  104. stats_after = pnic_after[name]
  105. templ = "%-15s %15s %15s"
  106. print_line(templ % (name, "TOTAL", "PER-SEC"), highlight=True)
  107. print_line(templ % (
  108. "bytes-sent",
  109. bytes2human(stats_after.bytes_sent),
  110. bytes2human(
  111. stats_after.bytes_sent - stats_before.bytes_sent) + '/s',
  112. ))
  113. print_line(templ % (
  114. "bytes-recv",
  115. bytes2human(stats_after.bytes_recv),
  116. bytes2human(
  117. stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
  118. ))
  119. print_line(templ % (
  120. "pkts-sent",
  121. stats_after.packets_sent,
  122. stats_after.packets_sent - stats_before.packets_sent,
  123. ))
  124. print_line(templ % (
  125. "pkts-recv",
  126. stats_after.packets_recv,
  127. stats_after.packets_recv - stats_before.packets_recv,
  128. ))
  129. print_line("")
  130. win.refresh()
  131. lineno = 0
  132. def main():
  133. try:
  134. interval = 0
  135. while True:
  136. args = poll(interval)
  137. refresh_window(*args)
  138. interval = 1
  139. except (KeyboardInterrupt, SystemExit):
  140. pass
  141. if __name__ == '__main__':
  142. main()