import subprocess import sys import os import psutil from pathlib import Path from logger_config import setup_logger # 设置日志记录器 logger = setup_logger('stop_scheduler') def stop_scheduler(): """停止定时任务进程和相关的sendmsg.py进程""" logger.info("=" * 50) logger.info("开始停止定时任务进程") logger.info("=" * 50) stopped_count = 0 current_dir = str(Path(__file__).parent) logger.info(f"当前工作目录: {current_dir}") # 方法0: 从PID文件中读取进程ID pid_file = Path(__file__).parent / "scheduler_pid.txt" if pid_file.exists(): logger.info(f"发现PID文件: {pid_file}") try: with open(pid_file, 'r') as f: pid = int(f.read().strip()) logger.info(f"从PID文件中读取到进程ID: {pid}") try: process = psutil.Process(pid) logger.info(f"找到进程: PID={pid}, 名称={process.name()}") logger.info(f"进程命令行: {' '.join(process.cmdline())}") process.terminate() logger.info(f"已发送终止信号给进程 PID={pid}") try: process.wait(timeout=5) # 等待进程正常结束 logger.info(f"进程 PID={pid} 已正常终止") except psutil.TimeoutExpired: logger.warning(f"进程 PID={pid} 未在5秒内终止,强制结束") process.kill() logger.info(f"已强制结束进程 PID={pid}") stopped_count += 1 # 删除PID文件 pid_file.unlink() logger.info("PID文件已删除") except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess) as e: logger.warning(f"PID文件中的进程 {pid} 已不存在或无法访问: {str(e)}") # 删除过期的PID文件 pid_file.unlink() logger.info("过期的PID文件已删除") except Exception as e: logger.error(f"从PID文件读取进程ID失败: {str(e)}") logger.error(f"错误类型: {type(e).__name__}") else: logger.info("未找到PID文件,尝试其他方法查找进程...") try: # 方法1: 使用psutil精确查找进程 logger.info("使用psutil查找相关进程...") for proc in psutil.process_iter(['pid', 'name', 'cmdline']): try: if proc.info['name'] in ['python.exe', 'pythonw.exe']: cmdline = proc.info['cmdline'] if cmdline and len(cmdline) > 1: # 检查是否是我们的scheduler.py或sendmsg.py进程 cmdline_str = ' '.join(cmdline) if ('scheduler.py' in cmdline_str or 'sendmsg.py' in cmdline_str) and current_dir in cmdline_str: logger.info(f"找到目标进程: PID={proc.info['pid']}") logger.info(f"进程名称: {proc.info['name']}") logger.info(f"命令行: {cmdline_str}") try: proc.terminate() logger.info(f"已发送终止信号给进程 PID={proc.info['pid']}") try: proc.wait(timeout=5) # 等待进程正常结束 logger.info(f"进程 PID={proc.info['pid']} 已正常终止") except psutil.TimeoutExpired: logger.warning(f"进程 PID={proc.info['pid']} 未在5秒内终止,强制结束") proc.kill() logger.info(f"已强制结束进程 PID={proc.info['pid']}") stopped_count += 1 except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess) as e: logger.warning(f"进程 {proc.info['pid']} 已不存在或无法访问: {str(e)}") except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess) as e: logger.debug(f"跳过进程 {proc.info.get('pid', 'unknown')}: {str(e)}") continue except ImportError: logger.warning("psutil模块未安装,使用备用方法...") # 方法2: 备用方法 - 改进的tasklist方式 try: logger.info("使用wmic命令查找进程...") # 获取详细的进程信息 result = subprocess.run(['wmic', 'process', 'where', 'name="pythonw.exe"', 'get', 'ProcessId,CommandLine', '/format:csv'], capture_output=True, text=True, encoding='gbk') lines = result.stdout.strip().split('\n') for line in lines[1:]: # 跳过标题行 if line.strip() and ('scheduler.py' in line or 'sendmsg.py' in line) and current_dir in line: logger.info(f"找到目标进程: {line}") # 提取PID parts = line.split(',') if len(parts) >= 2: pid = parts[-1].strip() if pid.isdigit(): logger.info(f"正在终止进程 PID={pid}") subprocess.run(['taskkill', '/F', '/PID', pid], check=True) logger.info(f"已终止进程 PID={pid}") stopped_count += 1 except subprocess.CalledProcessError as e: logger.error(f"wmic方法执行失败: {e}") # 方法3: 最后的备用方案 try: logger.info("使用tasklist命令查找进程...") result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq pythonw.exe', '/FO', 'CSV'], capture_output=True, text=True) if 'pythonw.exe' in result.stdout: logger.warning("警告: 找到pythonw.exe进程,但无法确定是否为目标进程") logger.warning("建议手动检查进程列表") logger.info("进程列表:") logger.info(result.stdout) response = input("是否强制结束所有pythonw.exe进程?(y/N): ") if response.lower() == 'y': logger.info("正在强制结束所有pythonw.exe进程...") subprocess.run(['taskkill', '/F', '/IM', 'pythonw.exe'], check=True) logger.info("已强制结束所有pythonw.exe进程") stopped_count += 1 except subprocess.CalledProcessError as e: logger.error(f"最后备用方案失败: {e}") # 总结报告 logger.info("=" * 50) if stopped_count > 0: logger.info(f"成功停止了 {stopped_count} 个定时任务相关进程(scheduler.py或sendmsg.py)") else: logger.info("未找到运行中的定时任务相关进程(scheduler.py或sendmsg.py)") logger.info("=" * 50) # 额外检查:查看是否还有相关进程 logger.info("检查剩余进程...") try: result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq pythonw.exe'], capture_output=True, text=True) if 'pythonw.exe' in result.stdout: logger.info("仍有pythonw.exe进程在运行:") logger.info(result.stdout) else: logger.info("没有发现pythonw.exe进程") except Exception as e: logger.warning(f"检查剩余进程失败: {str(e)}") if __name__ == "__main__": try: stop_scheduler() logger.info("程序执行完成") except Exception as e: logger.error(f"程序执行过程中出现未捕获的异常: {str(e)}") logger.error(f"异常类型: {type(e).__name__}") import traceback logger.error(f"异常堆栈: {traceback.format_exc()}") exit(1)