"""启动路由网关服务(后台、无窗口)。 用法: python scripts/serve.py [--port 8000] [--stop] """ import argparse import os import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent PID_FILE = ROOT / "_gateway.pid" def start(port: int): if PID_FILE.exists(): old = PID_FILE.read_text().strip() if old: print(f"已有服务运行 (pid={old}),先执行 --stop 再启动。") return out = open(ROOT / "_gateway.out.log", "ab", buffering=0) err = open(ROOT / "_gateway.err.log", "ab", buffering=0) flags = 0x00000008 | 0x08000000 # DETACHED_PROCESS | CREATE_NO_WINDOW proc = subprocess.Popen( [sys.executable, "-m", "uvicorn", "gateway.api:app", "--host", "127.0.0.1", "--port", str(port)], cwd=str(ROOT), stdout=out, stderr=err, creationflags=flags, close_fds=True, ) PID_FILE.write_text(str(proc.pid)) print(f"gateway 已启动 pid={proc.pid} port={port},日志: _gateway.out.log") def stop(): if not PID_FILE.exists(): print("没有运行中的服务。") return pid = int(PID_FILE.read_text().strip()) try: # Windows 下 SIGTERM 对 detached 进程不可靠,改用 taskkill 强制结束进程树 subprocess.run( ["taskkill", "/PID", str(pid), "/T", "/F"], capture_output=True, text=True, timeout=15, ) print(f"已终止服务 pid={pid}") except subprocess.TimeoutExpired: print(f"终止超时 pid={pid},请手动结束进程。") except Exception as e: print(f"终止失败(进程可能不存在): {e}") PID_FILE.unlink(missing_ok=True) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--port", type=int, default=8000) parser.add_argument("--stop", action="store_true", help="停止服务") args = parser.parse_args() if args.stop: stop() else: start(args.port)