197 lines
7.0 KiB
Python
197 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Kill Stale Processes Script
|
|
|
|
Safely terminates stale Python processes related to the trading dashboard
|
|
with proper error handling and graceful termination.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import signal
|
|
from pathlib import Path
|
|
import threading
|
|
|
|
# Global timeout flag
|
|
timeout_reached = False
|
|
|
|
def timeout_handler():
|
|
"""Handler for overall script timeout"""
|
|
global timeout_reached
|
|
timeout_reached = True
|
|
print("\n⚠️ WARNING: Script timeout reached (10s) - forcing exit")
|
|
os._exit(0) # Force exit
|
|
|
|
def kill_stale_processes():
|
|
"""Kill stale trading dashboard processes safely"""
|
|
global timeout_reached
|
|
|
|
# Set up overall timeout (10 seconds)
|
|
timer = threading.Timer(10.0, timeout_handler)
|
|
timer.daemon = True
|
|
timer.start()
|
|
|
|
try:
|
|
import psutil
|
|
except ImportError:
|
|
print("psutil not available - using fallback method")
|
|
return kill_stale_fallback()
|
|
|
|
current_pid = os.getpid()
|
|
killed_processes = []
|
|
failed_processes = []
|
|
|
|
# Keywords to identify trading dashboard processes
|
|
target_keywords = [
|
|
'dashboard', 'scalping', 'trading', 'tensorboard',
|
|
'run_clean', 'run_main', 'gogo2', 'mexc'
|
|
]
|
|
|
|
try:
|
|
print("Scanning for stale processes...")
|
|
|
|
# Get all Python processes with timeout
|
|
python_processes = []
|
|
scan_start = time.time()
|
|
|
|
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
|
|
if timeout_reached or (time.time() - scan_start) > 3.0: # 3s max for scanning
|
|
print("Process scanning timeout - proceeding with found processes")
|
|
break
|
|
|
|
try:
|
|
if proc.info['pid'] == current_pid:
|
|
continue
|
|
|
|
name = proc.info['name'].lower()
|
|
if 'python' in name or 'tensorboard' in name:
|
|
cmdline_str = ' '.join(proc.info['cmdline']) if proc.info['cmdline'] else ''
|
|
|
|
# Check if this is a target process
|
|
if any(keyword in cmdline_str.lower() for keyword in target_keywords):
|
|
python_processes.append({
|
|
'proc': proc,
|
|
'pid': proc.info['pid'],
|
|
'name': proc.info['name'],
|
|
'cmdline': cmdline_str
|
|
})
|
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
continue
|
|
|
|
if not python_processes:
|
|
print("No stale processes found")
|
|
timer.cancel() # Cancel the timeout
|
|
return True
|
|
|
|
print(f"Found {len(python_processes)} target processes to terminate:")
|
|
for p in python_processes[:5]: # Show max 5 to save time
|
|
print(f" - PID {p['pid']}: {p['name']} - {p['cmdline'][:80]}...")
|
|
if len(python_processes) > 5:
|
|
print(f" ... and {len(python_processes) - 5} more")
|
|
|
|
# Graceful termination first (with reduced wait time)
|
|
print("\nAttempting graceful termination...")
|
|
termination_start = time.time()
|
|
|
|
for p in python_processes:
|
|
if timeout_reached or (time.time() - termination_start) > 2.0:
|
|
print("Termination timeout - moving to force kill")
|
|
break
|
|
|
|
try:
|
|
proc = p['proc']
|
|
if proc.is_running():
|
|
proc.terminate()
|
|
print(f" Sent SIGTERM to PID {p['pid']}")
|
|
except Exception as e:
|
|
failed_processes.append(f"Failed to terminate PID {p['pid']}: {e}")
|
|
|
|
# Wait for graceful shutdown (reduced from 2.0 to 1.0)
|
|
time.sleep(1.0)
|
|
|
|
# Force kill remaining processes
|
|
print("\nChecking for remaining processes...")
|
|
kill_start = time.time()
|
|
|
|
for p in python_processes:
|
|
if timeout_reached or (time.time() - kill_start) > 2.0:
|
|
print("Force kill timeout - exiting")
|
|
break
|
|
|
|
try:
|
|
proc = p['proc']
|
|
if proc.is_running():
|
|
print(f" Force killing PID {p['pid']} ({p['name']})")
|
|
proc.kill()
|
|
killed_processes.append(f"Force killed PID {p['pid']} ({p['name']})")
|
|
else:
|
|
killed_processes.append(f"Gracefully terminated PID {p['pid']} ({p['name']})")
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
killed_processes.append(f"Process PID {p['pid']} already terminated")
|
|
except Exception as e:
|
|
failed_processes.append(f"Failed to kill PID {p['pid']}: {e}")
|
|
|
|
# Results (quick summary)
|
|
print(f"\n=== Quick Results ===")
|
|
print(f"✓ Cleaned up {len(killed_processes)} processes")
|
|
if failed_processes:
|
|
print(f"✗ Failed: {len(failed_processes)} processes")
|
|
|
|
timer.cancel() # Cancel the timeout if we finished early
|
|
return len(failed_processes) == 0
|
|
|
|
except Exception as e:
|
|
print(f"Error during process cleanup: {e}")
|
|
timer.cancel()
|
|
return False
|
|
|
|
def kill_stale_fallback():
|
|
"""Fallback method using basic OS commands"""
|
|
print("Using fallback process killing method...")
|
|
|
|
try:
|
|
if os.name == 'nt': # Windows
|
|
import subprocess
|
|
# Kill Python processes with dashboard keywords (with timeout)
|
|
result = subprocess.run([
|
|
'taskkill', '/f', '/im', 'python.exe'
|
|
], capture_output=True, text=True, timeout=5.0)
|
|
|
|
if result.returncode == 0:
|
|
print("Windows: Killed all Python processes")
|
|
else:
|
|
print("Windows: No Python processes to kill or access denied")
|
|
|
|
else: # Unix/Linux
|
|
import subprocess
|
|
# More targeted approach for Unix (with timeouts)
|
|
subprocess.run(['pkill', '-f', 'dashboard'], capture_output=True, timeout=2.0)
|
|
subprocess.run(['pkill', '-f', 'scalping'], capture_output=True, timeout=2.0)
|
|
subprocess.run(['pkill', '-f', 'tensorboard'], capture_output=True, timeout=2.0)
|
|
print("Unix: Killed dashboard-related processes")
|
|
|
|
return True
|
|
|
|
except subprocess.TimeoutExpired:
|
|
print("Fallback method timed out")
|
|
return False
|
|
except Exception as e:
|
|
print(f"Fallback method failed: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 50)
|
|
print("STALE PROCESS CLEANUP (10s timeout)")
|
|
print("=" * 50)
|
|
|
|
start_time = time.time()
|
|
success = kill_stale_processes()
|
|
elapsed = time.time() - start_time
|
|
|
|
exit_code = 0 if success else 1
|
|
|
|
print(f"Completed in {elapsed:.1f}s")
|
|
print("=" * 50)
|
|
sys.exit(exit_code) |