import os import time class ProcessTracker: FILE_PATH = "pids.txt" @staticmethod def register(name): """현재 프로세스의 PID와 이름을 기록""" pid = os.getpid() entry = f"{pid}: {name} (Started: {time.strftime('%Y-%m-%d %H:%M:%S')})\n" try: # 파일이 없으면 생성, 있으면 추가 # 단, main_server 시작 시 초기화하는 것이 좋음 with open(ProcessTracker.FILE_PATH, "a", encoding="utf-8") as f: f.write(entry) print(f"📌 Process Registered: {name} (PID: {pid})") except Exception as e: print(f"⚠️ Failed to register process: {e}") @staticmethod def check_and_kill_zombies(): """ pids.txt에 기록된 이전 프로세스들이 구동 중이라면 강제 종료. 서버 시작 시 1회 호출하여 좀비 프로세스를 정리함. """ if not os.path.exists(ProcessTracker.FILE_PATH): return print("🔍 Checking for zombie processes...") try: import psutil current_pid = os.getpid() with open(ProcessTracker.FILE_PATH, "r", encoding="utf-8") as f: lines = f.readlines() killed_count = 0 for line in lines: if ":" not in line or "Running Processes" in line: continue try: pid_str = line.split(":")[0].strip() pid = int(pid_str) if pid == current_pid: continue if psutil.pid_exists(pid): proc = psutil.Process(pid) proc_name = proc.name() # Python 프로세스만 타겟 if "python" in proc_name.lower(): print(f"💀 Killing Zombie Process: {pid} ({line.strip()})") proc.kill() killed_count += 1 except (ValueError, psutil.NoSuchProcess, psutil.AccessDenied): continue if killed_count > 0: print(f"✅ Cleaned up {killed_count} zombie processes.") # 파일 초기화 ProcessTracker.clear() except Exception as e: print(f"⚠️ Failed to kill zombies: {e}") @staticmethod def clear(): """PID 파일 초기화""" try: with open(ProcessTracker.FILE_PATH, "w", encoding="utf-8") as f: f.write(f"--- Running Processes (Last Update: {time.strftime('%Y-%m-%d %H:%M:%S')}) ---\n") except: pass