Files
tg-admin-bot/system_checks.py
2026-02-07 23:57:50 +03:00

147 lines
3.8 KiB
Python

import subprocess
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 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 disks() -> str:
disks = list_disks()
if not disks:
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}")
return "\n".join(lines)