Files
gogo2/kill_dashboard.py
2025-11-12 22:37:20 +02:00

226 lines
6.8 KiB
Python

#!/usr/bin/env python3
"""
Cross-platform script to kill stale Python dashboard processes.
Works on Linux, macOS, and Windows.
"""
import os
import sys
import signal
import psutil
import time
from pathlib import Path
# Dashboard script names to look for
DASHBOARD_SCRIPTS = [
'main_dashboard.py',
'run_clean_dashboard.py',
'web/clean_dashboard.py',
'web/cob_realtime_dashboard.py',
'ANNOTATE/web/app.py',
'COBY/main.py',
'run_integrated_rl_cob_dashboard.py',
'run_realtime_rl_cob_trader.py',
]
# Ports used by dashboards
DASHBOARD_PORTS = [8050, 8051, 8052, 8080, 8081, 5001]
def is_dashboard_process(proc):
"""Check if a process is a dashboard process"""
try:
# Get process info
cmdline = proc.cmdline()
if not cmdline:
return False
# Join command line for easier searching
cmd_str = ' '.join(cmdline).lower()
# Check if it's a Python process
if 'python' not in cmd_str:
return False
# Check if it's running one of our dashboard scripts
for script in DASHBOARD_SCRIPTS:
script_lower = script.lower()
if script_lower in cmd_str:
return True
# Check if it's using one of our dashboard ports
try:
connections = proc.connections()
for conn in connections:
if hasattr(conn, 'laddr') and conn.laddr:
if conn.laddr.port in DASHBOARD_PORTS:
return True
except (psutil.AccessDenied, psutil.NoSuchProcess):
pass
return False
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
return False
def kill_process(proc, force=False):
"""Kill a process gracefully or forcefully"""
try:
pid = proc.pid
name = proc.name()
if force:
# Force kill
if sys.platform == 'win32':
proc.kill()
else:
os.kill(pid, signal.SIGKILL)
print(f" Force killed PID {pid} ({name})")
else:
# Graceful termination
if sys.platform == 'win32':
proc.terminate()
else:
os.kill(pid, signal.SIGTERM)
print(f" Terminated PID {pid} ({name})")
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, ProcessLookupError) as e:
print(f" Could not kill PID {proc.pid}: {e}")
return False
def find_processes_on_ports():
"""Find processes listening on dashboard ports"""
port_processes = []
for proc in psutil.process_iter(['pid', 'name']):
try:
connections = proc.connections()
for conn in connections:
if hasattr(conn, 'laddr') and conn.laddr:
if conn.laddr.port in DASHBOARD_PORTS and conn.status == 'LISTEN':
port_processes.append({
'pid': proc.pid,
'name': proc.name(),
'port': conn.laddr.port
})
except (psutil.AccessDenied, psutil.NoSuchProcess):
pass
return port_processes
def main():
print("=" * 60)
print("Killing Stale Dashboard Processes")
print("=" * 60)
# Find dashboard processes
dashboard_procs = []
print("\nScanning for dashboard processes...")
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
if is_dashboard_process(proc):
dashboard_procs.append(proc)
if not dashboard_procs:
print(" No dashboard processes found")
else:
print(f" Found {len(dashboard_procs)} dashboard process(es):")
for proc in dashboard_procs:
try:
cmdline = ' '.join(proc.cmdline())
print(f" - PID {proc.pid}: {cmdline[:80]}{'...' if len(cmdline) > 80 else ''}")
except (psutil.NoSuchProcess, psutil.AccessDenied):
print(f" - PID {proc.pid}: (access denied)")
# Find processes on dashboard ports
print("\nChecking for processes on dashboard ports...")
port_procs = find_processes_on_ports()
if not port_procs:
print(" No processes found on dashboard ports")
else:
print(f" Found {len(port_procs)} process(es) on dashboard ports:")
for p in port_procs:
print(f" - PID {p['pid']} ({p['name']}) on port {p['port']}")
# Add to kill list if not already there
try:
proc = psutil.Process(p['pid'])
if proc not in dashboard_procs:
dashboard_procs.append(proc)
except psutil.NoSuchProcess:
pass
# Kill all found processes
if dashboard_procs:
print("\nTerminating processes...")
killed_count = 0
# First, try graceful termination
for proc in dashboard_procs:
if kill_process(proc, force=False):
killed_count += 1
# Wait for processes to exit
print("\nWaiting for processes to exit...")
time.sleep(2)
# Force kill any remaining processes
remaining = []
for proc in dashboard_procs:
try:
if proc.is_running():
remaining.append(proc)
except psutil.NoSuchProcess:
pass
if remaining:
print(f"\nForce killing {len(remaining)} remaining process(es)...")
for proc in remaining:
kill_process(proc, force=True)
print(f"\n✓ Killed {killed_count} dashboard process(es)")
else:
print("\n✓ No processes to kill")
print("\nPort status:")
for port in DASHBOARD_PORTS:
port_free = True
for proc in psutil.process_iter():
try:
for conn in proc.connections():
if hasattr(conn, 'laddr') and conn.laddr:
if conn.laddr.port == port and conn.status == 'LISTEN':
print(f" Port {port}: IN USE by PID {proc.pid}")
port_free = False
break
if not port_free:
break
except (psutil.AccessDenied, psutil.NoSuchProcess):
pass
if port_free:
print(f" Port {port}: FREE")
print("\n" + "=" * 60)
print("Process cleanup completed")
print("=" * 60)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print("\n\nInterrupted by user")
sys.exit(1)
except Exception as e:
print(f"\nError: {e}")
import traceback
traceback.print_exc()
sys.exit(1)