import subprocess import os def _cmd(cmd: str) -> str: """ Safe shell command runner """ try: return subprocess.getoutput(cmd) except Exception as e: return f"ERROR: {e}" # ---------- SECURITY ---------- def security() -> str: out = _cmd("sshd -T | grep -i '^permitrootlogin'") if not out or "ERROR:" in out: return "šŸ” Security\n\nāš ļø permitrootlogin not found" lines = ["šŸ” Security\n"] if "no" in out.lower(): lines.append("🟢 Root login disabled") else: lines.append("šŸ”“ Root login ENABLED") pass_auth = _cmd("sshd -T | grep -i '^passwordauthentication'") if pass_auth and "ERROR:" not in pass_auth: lines.append("šŸ”“ Password auth enabled" if "yes" in pass_auth.lower() else "🟢 Password auth disabled") pubkey_auth = _cmd("sshd -T | grep -i '^pubkeyauthentication'") if pubkey_auth and "ERROR:" not in pubkey_auth: lines.append("🟢 Pubkey auth enabled" if "yes" in pubkey_auth.lower() else "šŸ”“ Pubkey auth disabled") sec_updates = _cmd("apt list --upgradable 2>/dev/null | grep -i security | wc -l") if sec_updates and "ERROR:" not in sec_updates: try: count = int(sec_updates.strip()) lines.append(f"šŸ”” Security updates: {count}") except ValueError: pass time_info = _cmd("timedatectl") if time_info and "ERROR:" not in time_info: tz = None ntp = None synced = None for line in time_info.splitlines(): if "Time zone:" in line: tz = line.split("Time zone:", 1)[1].strip() if "NTP service:" in line: ntp = line.split("NTP service:", 1)[1].strip() if "System clock synchronized:" in line: synced = line.split("System clock synchronized:", 1)[1].strip() if tz: lines.append(f"šŸ•’ Time zone: {tz}") if ntp: lines.append(f"šŸ”§ NTP service: {ntp}") if synced: lines.append(f"ā± Clock synced: {synced}") return "\n".join(lines) # ---------- DISKS ---------- def list_disks() -> list[str]: out = _cmd("lsblk -dn -o NAME,TYPE") disks = [] for line in out.splitlines(): parts = line.split() if len(parts) != 2: continue name, typ = parts if typ == "disk": disks.append(f"/dev/{name}") return disks def list_md_arrays() -> list[str]: out = _cmd("lsblk -dn -o NAME,TYPE") arrays = [] for line in out.splitlines(): parts = line.split() if len(parts) != 2: continue name, typ = parts if typ.startswith("raid") and name.startswith("md"): arrays.append(f"/dev/{name}") return arrays def md_array_status(dev: str) -> str: out = _cmd("cat /proc/mdstat") if not out or "ERROR:" in out: return "āš ļø n/a" name = dev.rsplit("/", 1)[-1] lines = out.splitlines() header = None idx = -1 for i, line in enumerate(lines): s = line.strip() if s.startswith(f"{name} :"): header = s idx = i break if not header: return "āš ļø not found in /proc/mdstat" if "inactive" in header: return "šŸ”“ inactive" # Typical mdstat health marker: [UU] for healthy mirrors/raid members. block = [header] for line in lines[idx + 1:]: if not line.strip(): break block.append(line.strip()) block_text = " ".join(block) if "[U_" in block_text or "[_U" in block_text: return "🟔 degraded" return "🟢 active" def smart_health(dev: str) -> str: out = _cmd(f"smartctl -H {dev}") if not out or "ERROR:" in out: return "āš ļø ERROR" if "PASSED" in out: return "🟢 PASSED" if "FAILED" in out: return "šŸ”“ FAILED" return "āš ļø UNKNOWN" def disk_temperature(dev: str) -> str: out = _cmd(f"smartctl -A {dev}") if not out or "ERROR:" in out: return "n/a" # NVMe for line in out.splitlines(): if "Temperature:" in line and "Celsius" in line: try: temp = int("".join(filter(str.isdigit, line))) return f"{temp}°C" except Exception: pass # SATA attributes for line in out.splitlines(): if line.strip().startswith(("194", "190")): parts = line.split() for p in parts[::-1]: if p.isdigit(): return f"{p}°C" return "n/a" def smart_last_test(dev: str) -> str: out = _cmd(f"smartctl -l selftest {dev}") if not out or "ERROR:" in out: return "n/a" for line in out.splitlines(): if "No self-tests have been logged" in line: return "no tests" if line.lstrip().startswith("#"): return line.strip() return "n/a" def disks() -> str: disks = list_disks() md_arrays = list_md_arrays() if not disks and not md_arrays: return "šŸ’½ Disks\n\nāŒ No disks found" lines = ["šŸ’½ Disks (SMART)\n"] for d in disks: health = smart_health(d) temp = disk_temperature(d) icon = "🟢" if temp != "n/a": t = int(temp.replace("°C", "")) if t > 50: icon = "šŸ”“" elif t > 40: icon = "🟔" lines.append(f"{icon} {d} — {health}, 🌔 {temp}") if md_arrays: lines.append("") lines.append("🧱 RAID (md)") for md in md_arrays: lines.append(f"{md} — {md_array_status(md)}") return "\n".join(lines) def hardware() -> str: cpu_model = "n/a" try: with open("/proc/cpuinfo", "r") as f: for line in f: if line.lower().startswith("model name"): cpu_model = line.split(":", 1)[1].strip() break except Exception: pass mem_total = "n/a" swap_total = "n/a" try: with open("/proc/meminfo", "r") as f: for line in f: if line.startswith("MemTotal:"): mem_kb = int(line.split()[1]) mem_total = f"{mem_kb / (1024**2):.2f} GiB" if line.startswith("SwapTotal:"): swap_kb = int(line.split()[1]) swap_total = f"{swap_kb / (1024**2):.2f} GiB" except Exception: pass cores = os.cpu_count() or "n/a" uname = os.uname() lines = [ "🧱 Hardware", "", f"🧠 CPU: {cpu_model}", f"🧩 Cores: {cores}", f"šŸ’¾ RAM: {mem_total}", f"šŸŒ€ Swap: {swap_total}", f"🧬 Arch: {uname.machine}", f"🐧 Kernel: {uname.release}", ] gpu_lines = _gpu_info() if gpu_lines: lines.append("") lines.extend(gpu_lines) return "\n".join(lines) def _gpu_info() -> list[str]: # 1) NVIDIA: use nvidia-smi if available for model + memory smi = _cmd("nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader") if smi and "ERROR:" not in smi and "not found" not in smi.lower(): lines = ["šŸŽ® GPU (NVIDIA)"] for line in smi.splitlines(): parts = [p.strip() for p in line.split(",")] if len(parts) >= 2: name = parts[0] mem = parts[1] drv = parts[2] if len(parts) > 2 else "n/a" lines.append(f"• {name} | {mem} | driver {drv}") return lines # 2) Generic: lspci (VGA/3D/Display) lspci = _cmd("lspci -mm | egrep -i 'vga|3d|display'") if lspci and "ERROR:" not in lspci and "not found" not in lspci.lower(): lines = ["šŸŽ® GPU"] for line in lspci.splitlines(): # Format: "00:02.0" "VGA compatible controller" "Intel Corporation" "..." parts = [p.strip().strip('"') for p in line.split('"') if p.strip()] if len(parts) >= 4: vendor = parts[2] model = parts[3] lines.append(f"• {vendor} {model}") elif line.strip(): lines.append(f"• {line.strip()}") # Try AMD VRAM from sysfs if present vram = _cmd("cat /sys/class/drm/card*/device/mem_info_vram_total 2>/dev/null | head -n 1") if vram and vram.strip().isdigit(): bytes_val = int(vram.strip()) lines.append(f"• VRAM: {bytes_val / (1024**3):.2f} GiB") return lines return []