Last active
December 16, 2025 09:04
-
-
Save fragtion/7507ccfc270acef5c1cc7a7ff3ac0943 to your computer and use it in GitHub Desktop.
ifstat script for WSL1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Cross-platform network traffic monitor (ifstat style) | |
| - Windows: uses PowerShell `Get-NetAdapterStatistics` (Works on WSL1) | |
| - Linux: reads `/proc/net/dev` | |
| Displays per-interface KB/s in and KB/s out, updated once per second. | |
| """ | |
| import sys | |
| import time | |
| import json | |
| import textwrap | |
| import subprocess | |
| import platform | |
| col_width = 10 | |
| label_width = col_width * 2 | |
| # -------------------- Platform-specific functions -------------------- # | |
| def powershell_stream(): | |
| """Stream Windows adapter stats via PowerShell""" | |
| ps_cmd = """ | |
| while ($true) { | |
| Get-NetAdapterStatistics | | |
| Select-Object Name,ReceivedBytes,SentBytes | | |
| ConvertTo-Json -Compress; | |
| Start-Sleep -Seconds 1 | |
| } | |
| """ | |
| return subprocess.Popen( | |
| ["/mnt/c/Windows/SysWOW64/WindowsPowerShell/v1.0/powershell.exe" | |
| if platform.system() == "Linux" and "Microsoft" in platform.release() | |
| else "powershell.exe", | |
| "-Command", ps_cmd], | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.DEVNULL, | |
| text=True, | |
| bufsize=1 | |
| ) | |
| def parse_stats_windows(line): | |
| try: | |
| data = json.loads(line.strip()) | |
| if isinstance(data, dict): | |
| data = [data] | |
| stats = {} | |
| for entry in data: | |
| adapter = entry["Name"] | |
| stats[adapter] = (int(entry["ReceivedBytes"]), int(entry["SentBytes"])) | |
| return stats | |
| except Exception: | |
| return {} | |
| def read_stats_linux(): | |
| stats = {} | |
| try: | |
| with open("/proc/net/dev") as f: | |
| for line in f: | |
| if ":" not in line: | |
| continue | |
| iface, data = line.split(":", 1) | |
| iface = iface.strip() | |
| fields = data.split() | |
| stats[iface] = (int(fields[0]), int(fields[8])) | |
| except Exception: | |
| pass | |
| return stats | |
| # -------------------- Initialization -------------------- # | |
| if sys.platform.startswith("win") or ("Microsoft" in platform.release()): | |
| proc = powershell_stream() | |
| first_line = proc.stdout.readline() | |
| prev_stats = parse_stats_windows(first_line) | |
| read_stats = lambda: parse_stats_windows(proc.stdout.readline()) | |
| else: | |
| prev_stats = read_stats_linux() | |
| read_stats = read_stats_linux | |
| if not prev_stats: | |
| print("No network interfaces found.") | |
| sys.exit(1) | |
| adapters = list(prev_stats.keys()) | |
| # Wrap interface names | |
| wrapped_names = [] | |
| max_lines = 0 | |
| for adapter in adapters: | |
| wrapped = textwrap.wrap(adapter, label_width) | |
| wrapped_names.append(wrapped) | |
| max_lines = max(max_lines, len(wrapped)) | |
| print("Starting network traffic monitoring. Press Ctrl+C to stop.\n") | |
| for line in range(max_lines): | |
| parts = [] | |
| for wrapped in wrapped_names: | |
| text = wrapped[line] if line < len(wrapped) else "" | |
| parts.append(f"{text:^{label_width}}") | |
| print(" ".join(parts)) | |
| subheader = " ".join( | |
| f"{'KB/s in':>{col_width}}{'KB/s out':>{col_width}}" for _ in adapters | |
| ) | |
| print(subheader) | |
| prev_time = time.time() | |
| # -------------------- Monitoring loop -------------------- # | |
| try: | |
| while True: | |
| time.sleep(1) | |
| current_stats = read_stats() | |
| if not current_stats: | |
| continue | |
| current_time = time.time() | |
| delta_time = current_time - prev_time | |
| line_parts = [] | |
| for adapter in adapters: | |
| if adapter in current_stats and adapter in prev_stats: | |
| prev_rx, prev_tx = prev_stats[adapter] | |
| curr_rx, curr_tx = current_stats[adapter] | |
| delta_rx = (curr_rx - prev_rx) / delta_time / 1024 | |
| delta_tx = (curr_tx - prev_tx) / delta_time / 1024 | |
| rx_str = f"{delta_rx:>{col_width}.2f}" | |
| tx_str = f"{delta_tx:>{col_width}.2f}" | |
| line_parts.append(f"{rx_str}{tx_str}") | |
| else: | |
| line_parts.append(f"{'0.00':>{col_width}}{'0.00':>{col_width}}") | |
| print(" ".join(line_parts)) | |
| prev_stats = current_stats | |
| prev_time = current_time | |
| except KeyboardInterrupt: | |
| if sys.platform.startswith("win") or ("Microsoft" in platform.release()): | |
| proc.terminate() | |
| print("\nMonitoring stopped.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment