#!/usr/bin/env python3 """ sysmon - System monitor Quick system status and resource tracking. """ import os import json import subprocess from datetime import datetime from pathlib import Path WORKSPACE = Path("/home/wdjones/.openclaw/workspace") HISTORY_FILE = WORKSPACE / "data" / "sysmon_history.json" def get_cpu_usage(): """Get CPU usage percentage.""" try: # Read /proc/stat for CPU usage with open('/proc/stat') as f: line = f.readline() parts = line.split() idle = int(parts[4]) total = sum(int(p) for p in parts[1:]) # Read again after a moment import time time.sleep(0.1) with open('/proc/stat') as f: line = f.readline() parts = line.split() idle2 = int(parts[4]) total2 = sum(int(p) for p in parts[1:]) idle_delta = idle2 - idle total_delta = total2 - total if total_delta == 0: return 0 usage = 100 * (1 - idle_delta / total_delta) return round(usage, 1) except: return None def get_memory(): """Get memory usage.""" try: with open('/proc/meminfo') as f: lines = f.readlines() mem = {} for line in lines: parts = line.split() key = parts[0].rstrip(':') value = int(parts[1]) # in KB mem[key] = value total = mem.get('MemTotal', 0) / 1024 / 1024 # GB available = mem.get('MemAvailable', 0) / 1024 / 1024 # GB used = total - available pct = (used / total * 100) if total > 0 else 0 return { 'total_gb': round(total, 1), 'used_gb': round(used, 1), 'available_gb': round(available, 1), 'percent': round(pct, 1), } except: return None def get_disk(): """Get disk usage.""" try: stat = os.statvfs('/') total = stat.f_blocks * stat.f_frsize / 1024 / 1024 / 1024 # GB free = stat.f_bavail * stat.f_frsize / 1024 / 1024 / 1024 # GB used = total - free pct = (used / total * 100) if total > 0 else 0 return { 'total_gb': round(total, 1), 'used_gb': round(used, 1), 'free_gb': round(free, 1), 'percent': round(pct, 1), } except: return None def get_load(): """Get system load average.""" try: with open('/proc/loadavg') as f: parts = f.read().split() return { 'load1': float(parts[0]), 'load5': float(parts[1]), 'load15': float(parts[2]), } except: return None def get_uptime(): """Get system uptime.""" try: with open('/proc/uptime') as f: uptime_seconds = float(f.read().split()[0]) days = int(uptime_seconds // 86400) hours = int((uptime_seconds % 86400) // 3600) mins = int((uptime_seconds % 3600) // 60) if days > 0: return f"{days}d {hours}h {mins}m" elif hours > 0: return f"{hours}h {mins}m" else: return f"{mins}m" except: return None def get_processes(): """Get top processes by memory/CPU.""" try: result = subprocess.run( ['ps', 'aux', '--sort=-rss'], capture_output=True, text=True ) lines = result.stdout.strip().split('\n')[1:6] # Skip header, top 5 processes = [] for line in lines: parts = line.split(None, 10) if len(parts) >= 11: processes.append({ 'user': parts[0], 'cpu': float(parts[2]), 'mem': float(parts[3]), 'cmd': parts[10][:30], }) return processes except: return [] def bar(pct: float, width: int = 20) -> str: """Create a progress bar.""" filled = int(pct / 100 * width) return "█" * filled + "░" * (width - filled) def show_status(): """Show current system status.""" print() print("╔" + "═" * 40 + "╗") print(f"║ 🖥️ System Monitor {' ' * 20}║") print("╚" + "═" * 40 + "╝") # Uptime uptime = get_uptime() if uptime: print(f"\n⏰ Uptime: {uptime}") # CPU cpu = get_cpu_usage() if cpu is not None: print(f"\n🔲 CPU: {bar(cpu)} {cpu}%") # Memory mem = get_memory() if mem: print(f"🔲 Memory: {bar(mem['percent'])} {mem['percent']}%") print(f" {mem['used_gb']:.1f}GB / {mem['total_gb']:.1f}GB") # Disk disk = get_disk() if disk: print(f"🔲 Disk: {bar(disk['percent'])} {disk['percent']}%") print(f" {disk['used_gb']:.0f}GB / {disk['total_gb']:.0f}GB") # Load load = get_load() if load: print(f"\n📊 Load: {load['load1']:.2f} / {load['load5']:.2f} / {load['load15']:.2f}") # Top processes procs = get_processes() if procs: print(f"\n🔝 Top Processes:") for p in procs[:3]: print(f" {p['mem']:.1f}% {p['cmd']}") print() def record(): """Record current stats to history.""" HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True) if HISTORY_FILE.exists(): with open(HISTORY_FILE) as f: history = json.load(f) else: history = [] entry = { 'timestamp': datetime.now().isoformat(), 'cpu': get_cpu_usage(), 'memory': get_memory(), 'disk': get_disk(), 'load': get_load(), } history.append(entry) # Keep last 1000 entries history = history[-1000:] with open(HISTORY_FILE, 'w') as f: json.dump(history, f) print(f"✓ Recorded at {entry['timestamp'][:19]}") def main(): import sys if len(sys.argv) > 1: cmd = sys.argv[1] if cmd == 'record': record() else: print("Usage: sysmon [record]") else: show_status() if __name__ == "__main__": main()