#!/usr/bin/env python3 """Limpieza de procesos de la Pi: mata procesos zombie/atascados, reinicia servicios si es necesario.""" import subprocess import os import sys import time sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import config def sh(cmd): try: return subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=15).stdout.strip() except Exception: return "" def limpiar(): informe = [] # 1. Procesos Python atascados (CPU > 50% durante >60s) ps = sh("ps aux | grep python3 | grep -v grep") for linea in ps.splitlines(): if not linea: continue parts = linea.split() try: cpu = float(parts[2]) pid = parts[1] cmd = " ".join(parts[10:]) if cpu > 50 and "minipc" in cmd: informe.append(f"Matando proceso atascado PID {pid} ({cpu}% CPU): {cmd[:50]}") sh(f"kill -9 {pid}") except (IndexError, ValueError): pass # 2. Zombie processes zombies = sh("ps aux | awk '$8==\"Z\" {print $2}'") for z in zombies.splitlines(): if z.strip(): informe.append(f"Zombie PID {z.strip()} limpiado") sh(f"kill -9 {z.strip()}") # 3. Procesos python viejos (>2h, sin ser servicios principales) ps2 = sh("ps aux | grep python3 | grep -v grep") for linea in ps2.splitlines(): if not linea: continue parts = linea.split() try: pid = parts[1] starttime = parts[8] cmd = " ".join(parts[10:]) if "tv_api" not in cmd and "pi_bot" not in cmd and "http.server" not in cmd: if "python" in cmd.lower() or "vigilancia" in cmd.lower(): informe.append(f"Proceso residual PID {pid}: {cmd[:60]}") except (IndexError, ValueError): pass # 4. Limpiar cache del sistema sh("echo 'raspberry' | sudo -S sync") sh("echo 'raspberry' | sudo -S sh -c 'echo 3 > /proc/sys/vm/drop_caches'") informe.append("Caché del sistema limpiado") # 5. Verificar servicios for svc in ["tv-api", "pi-bot"]: st = sh(f"systemctl is-active {svc}") if st != "active": informe.append(f"⚠️ Servicio {svc} no activo: {st}") sh(f"echo 'raspberry' | sudo -S systemctl restart {svc}") # 6. Estado final temp = sh("vcgencmd measure_temp") load = sh("cat /proc/loadavg | cut -d' ' -f1") mem = sh("free -h | awk 'NR==2{print $2\" total, \"$7\" libre\"}'") if not informe: informe.append("✅ Todo limpio, sin procesos atascados") informe.append(f"\nEstado: temp={temp} | load={load} | mem={mem}") return "\n".join(informe) if __name__ == "__main__": print(limpiar())