#!/usr/bin/env python # -*- coding: utf-8 -*- """ VWED任务系统服务管理工具 用于管理VWED服务的启动、停止、状态检查等操作 """ import os import sys import time import signal import psutil import argparse import subprocess from pathlib import Path class VWEDServiceManager: """VWED服务管理器""" def __init__(self): self.service_name = "VWED_Task_System.exe" self.pid_file = Path("vwed_service.pid") self.log_file = Path("vwed_service.log") self.config_file = Path("config.ini") def start_service(self, headless=True, wait_for_start=True): """启动服务""" if self.is_running(): print("服务已在运行中") return True print("启动VWED服务...") # 构建启动命令 cmd = [self.service_name] if headless: cmd.append("--headless") try: # 启动服务进程 if headless: # 后台模式,重定向输出到日志文件 with open(self.log_file, 'a', encoding='utf-8') as log_f: process = subprocess.Popen( cmd, stdout=log_f, stderr=subprocess.STDOUT, cwd=Path.cwd(), creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0 ) else: # 前台模式 process = subprocess.Popen(cmd, cwd=Path.cwd()) # 记录PID with open(self.pid_file, 'w') as f: f.write(str(process.pid)) print(f"服务已启动 (PID: {process.pid})") if wait_for_start: # 等待服务完全启动 print("等待服务启动完成...") for i in range(30): # 最多等待30秒 if self._check_service_port(): print("服务启动成功,可以访问 http://localhost:8000") return True time.sleep(1) print("警告: 服务可能未完全启动,请检查日志文件") return True except FileNotFoundError: print(f"错误: 找不到可执行文件 {self.service_name}") return False except Exception as e: print(f"启动服务失败: {e}") return False def stop_service(self, force=False): """停止服务""" if not self.is_running(): print("服务未运行") self._cleanup_pid_file() return True try: pid = self._get_pid() if pid: print(f"正在停止服务 (PID: {pid})...") try: process = psutil.Process(pid) if not force: # 优雅关闭 process.terminate() # 等待进程结束 try: process.wait(timeout=10) print("服务已优雅停止") except psutil.TimeoutExpired: print("优雅停止超时,强制停止服务...") process.kill() print("服务已强制停止") else: # 强制关闭 process.kill() print("服务已强制停止") except psutil.NoSuchProcess: print("进程不存在,清理PID文件") self._cleanup_pid_file() return True except Exception as e: print(f"停止服务失败: {e}") return False def restart_service(self, headless=True): """重启服务""" print("重启服务...") if self.is_running(): if not self.stop_service(): return False # 等待进程完全停止 time.sleep(2) return self.start_service(headless) def service_status(self, show_logs=True): """检查服务状态""" print("检查VWED服务状态...") print("-" * 50) # 检查进程状态 if self.is_running(): pid = self._get_pid() try: process = psutil.Process(pid) print(f"✓ 服务正在运行") print(f" PID: {pid}") print(f" 内存使用: {process.memory_info().rss / 1024 / 1024:.1f} MB") print(f" CPU使用率: {process.cpu_percent():.1f}%") print(f" 运行时间: {time.time() - process.create_time():.0f} 秒") except psutil.NoSuchProcess: print("✗ 进程不存在,清理PID文件") self._cleanup_pid_file() return False else: print("✗ 服务未运行") # 检查端口状态 if self._check_service_port(): print("✓ 服务端口 8000 可访问") print(" 访问地址: http://localhost:8000") else: print("✗ 服务端口 8000 不可访问") # 检查配置文件 if self.config_file.exists(): print("✓ 配置文件存在") else: print("✗ 配置文件不存在") # 显示最近日志 if show_logs and self.log_file.exists(): print("\n最近的日志内容:") print("-" * 30) try: with open(self.log_file, 'r', encoding='utf-8') as f: lines = f.readlines() for line in lines[-10:]: # 显示最后10行 print(line.strip()) except Exception as e: print(f"读取日志失败: {e}") return self.is_running() def is_running(self): """检查服务是否运行中""" pid = self._get_pid() if not pid: return False try: return psutil.pid_exists(pid) except: return False def _get_pid(self): """获取服务PID""" if not self.pid_file.exists(): return None try: with open(self.pid_file, 'r') as f: return int(f.read().strip()) except (ValueError, FileNotFoundError): return None def _cleanup_pid_file(self): """清理PID文件""" if self.pid_file.exists(): try: self.pid_file.unlink() except: pass def _check_service_port(self): """检查服务端口是否可访问""" try: import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(1) result = s.connect_ex(('localhost', 8000)) return result == 0 except: return False def main(): """主函数""" parser = argparse.ArgumentParser(description='VWED任务系统服务管理工具') parser.add_argument('action', choices=['start', 'stop', 'restart', 'status', 'logs'], help='操作: start(启动), stop(停止), restart(重启), status(状态), logs(查看日志)') parser.add_argument('--headless', action='store_true', help='后台模式运行(适用于start和restart)') parser.add_argument('--force', action='store_true', help='强制停止服务(适用于stop)') parser.add_argument('--no-wait', action='store_true', help='启动后不等待服务完全启动(适用于start)') args = parser.parse_args() manager = VWEDServiceManager() try: if args.action == 'start': success = manager.start_service( headless=args.headless, wait_for_start=not args.no_wait ) sys.exit(0 if success else 1) elif args.action == 'stop': success = manager.stop_service(force=args.force) sys.exit(0 if success else 1) elif args.action == 'restart': success = manager.restart_service(headless=args.headless) sys.exit(0 if success else 1) elif args.action == 'status': is_running = manager.service_status() sys.exit(0 if is_running else 1) elif args.action == 'logs': if manager.log_file.exists(): try: with open(manager.log_file, 'r', encoding='utf-8') as f: print(f.read()) except Exception as e: print(f"读取日志失败: {e}") sys.exit(1) else: print("日志文件不存在") sys.exit(1) except KeyboardInterrupt: print("\n操作被用户中断") sys.exit(1) except Exception as e: print(f"操作失败: {e}") sys.exit(1) if __name__ == "__main__": main()