- 修改config.py中的文件路径和定时发送时间 - 在各个脚本中添加日志记录功能,提升错误追踪和调试能力 - 更新README.md,详细说明程序功能和使用方法 - 重构scheduler.py、sendmsg.py、send_openmsg.py和send_filemsg.py,增强代码可读性和可维护性
179 lines
8.4 KiB
Python
179 lines
8.4 KiB
Python
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) |