#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ CURRENT REALITY хоста — компактно и по факту. Только чтение. Шесть полей: runtime · source root · git/NON_GIT · public URL · active writer · blocker. """ import os, re, subprocess def sh(c, t=90): try: r = subprocess.run(c, shell=True, capture_output=True, text=True, timeout=t) return (r.stdout or r.stderr or "").strip() except Exception as e: return f"<{type(e).__name__}>" print("HOST ", sh("hostname"), "·", sh(". /etc/os-release && echo $PRETTY_NAME")) print("UPTIME ", sh("uptime -p"), "· загрузка", sh("cut -d' ' -f1-3 /proc/loadavg")) print("RESOURCES ", sh("free -m | awk '/^Mem:/{print $3\"/\"$2\" МБ\"}'"), "· диск", sh("df -h / | awk 'NR==2{print $3\"/\"$2\" (\"$5\")\"}'")) print("\n--- RUNTIME ---") units = sh("systemctl list-units --type=service --state=running --no-legend --no-pager | awk '{print $1}'") prof = [u for u in units.splitlines() if re.search(r"arena|grid|arb|bot|trade|api|caddy|nginx|postgres|grafana|redis|docker", u)] print(f" сервисов всего {len(units.splitlines())}, профильных {len(prof)}") for u in prof[:12]: print(f" {u}") print(" упавших:", sh("systemctl list-units --state=failed --no-legend --no-pager | wc -l")) print(" python-процессов:", sh("pgrep -c python3 || echo 0")) print(" docker:", (sh("docker ps --format '{{.Names}}:{{.Image}}' 2>/dev/null | head -4") or "нет").replace("\n", " · ")) print("\n--- ПОРТЫ ---") for ln in sh("ss -lntp 2>/dev/null | awk 'NR>1{print $4, $6}' | sort -u").splitlines()[:12]: m = re.search(r'users:\(\("([^"]+)"', ln) print(f" {ln.split()[0]:24} {m.group(1) if m else ''}") print("\n--- SOURCE ROOT / GIT ---") cands = sh("ls -d /opt/*/ /srv/*/ /home/*/ /root/*/ 2>/dev/null | head -20") found = False for d in cands.splitlines(): d = d.rstrip("/") n = sh(f"find {d} -maxdepth 2 -name '*.py' 2>/dev/null | wc -l") if not n.isdigit() or int(n) < 2: continue found = True sz = sh(f"du -xsh {d} 2>/dev/null | cut -f1") if os.path.isdir(os.path.join(d, ".git")): br = sh(f"git -C {d} rev-parse --abbrev-ref HEAD 2>/dev/null") last = sh(f"git -C {d} log -1 --format='%h %ad %s' --date=short 2>/dev/null")[:46] dirty = sh(f"git -C {d} status --porcelain 2>/dev/null | wc -l") print(f" {d:28} {n:>4} py · {sz:>6} · GIT {br} · {last} · грязных {dirty}") else: print(f" {d:28} {n:>4} py · {sz:>6} · **NON_GIT**") if not found: print(" каталогов с кодом не найдено") print("\n--- ПОСЛЕДНИЕ ПРАВКИ (7 суток) ---") r = sh("find /opt /srv /root /home -maxdepth 3 -name '*.py' -mtime -7 " "-printf '%TY-%Tm-%Td %TH:%TM %p\\n' 2>/dev/null | sort -r | head -6") print("\n".join(" " + x for x in r.splitlines()) or " нет правок за неделю") print("\n--- ACTIVE WRITER (кто пишет данные) ---") print(" БД локально:", (sh("ss -lntp 2>/dev/null | grep -cE ':(5432|3306|27017)'") or "0"), "слушателей") w = sh("find /opt /srv /root /home -maxdepth 3 \\( -name '*.db' -o -name '*.sqlite*' -o -name '*.log' -o -name '*.jsonl' \\) " "-mmin -120 -printf '%TH:%TM %s %p\\n' 2>/dev/null | sort -r | head -6") print(" файлы, тронутые за 2 часа:") print("\n".join(" " + x for x in w.splitlines()) or " нет — данные никуда не пишутся локально") print("\n--- ИСХОДЯЩИЕ СОЕДИНЕНИЯ ---") print(sh("ss -tnp state established 2>/dev/null | awk 'NR>1{print $4\" -> \"$5}' | sort -u | head -6") or " нет")