145 lines
3.7 KiB
Python
145 lines
3.7 KiB
Python
"""
|
|
agent_jrxml 统一启动/停止脚本
|
|
用法: python start.py [--frontend]
|
|
"""
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import signal
|
|
import os
|
|
import socket
|
|
|
|
PROCESSES = []
|
|
|
|
def kill_port(port):
|
|
"""杀掉占用指定端口的所有进程"""
|
|
killed = []
|
|
try:
|
|
result = subprocess.run(
|
|
['netstat', '-ano'], capture_output=True, text=True, timeout=10
|
|
)
|
|
for line in result.stdout.splitlines():
|
|
if f':{port}' in line and 'LISTENING' in line:
|
|
parts = line.strip().split()
|
|
pid = parts[-1]
|
|
try:
|
|
subprocess.run(['taskkill', '/F', '/PID', pid],
|
|
capture_output=True, timeout=5)
|
|
killed.append(pid)
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
if killed:
|
|
print(f"[清理] 端口 {port} 已清理 {len(killed)} 个进程: {', '.join(killed)}")
|
|
return len(killed)
|
|
|
|
|
|
def wait_port(port, timeout=30):
|
|
"""等待端口就绪"""
|
|
for i in range(timeout * 2):
|
|
try:
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
s.settimeout(1)
|
|
s.connect(('127.0.0.1', port))
|
|
s.close()
|
|
return True
|
|
except:
|
|
time.sleep(0.5)
|
|
return False
|
|
|
|
|
|
def start(port, module, cwd=None):
|
|
"""启动一个 uvicorn 服务"""
|
|
cmd = [
|
|
sys.executable, '-c',
|
|
f"import uvicorn; uvicorn.run('{module}', host='0.0.0.0', port={port}, reload=False)"
|
|
]
|
|
proc = subprocess.Popen(cmd, cwd=cwd)
|
|
PROCESSES.append((port, proc))
|
|
print(f"[启动] {module} -> :{port} (PID: {proc.pid})")
|
|
return proc
|
|
|
|
|
|
def cleanup():
|
|
"""清理所有子进程"""
|
|
print("\n[清理] 正在停止所有服务...")
|
|
for port, proc in PROCESSES:
|
|
try:
|
|
proc.terminate()
|
|
except:
|
|
pass
|
|
time.sleep(2)
|
|
for port, proc in PROCESSES:
|
|
try:
|
|
proc.kill()
|
|
except:
|
|
pass
|
|
kill_port(port)
|
|
print("[清理] 完成")
|
|
|
|
|
|
def main():
|
|
frontend = '--frontend' in sys.argv
|
|
|
|
# 1. 清理残留进程
|
|
print("=" * 50)
|
|
print("agent_jrxml 启动脚本")
|
|
print("=" * 50)
|
|
kill_port(8000)
|
|
kill_port(8001)
|
|
if frontend:
|
|
kill_port(5173)
|
|
|
|
# 2. 启动服务(基于脚本所在目录自动定位项目)
|
|
project = os.path.dirname(os.path.abspath(__file__))
|
|
start(8000, 'api_server:app', cwd=project)
|
|
start(8001, 'validation_service.main:app', cwd=project)
|
|
|
|
if frontend:
|
|
# 前端用 npm 启动
|
|
frontend_dir = os.path.join(project, 'frontend')
|
|
proc = subprocess.Popen(
|
|
['npm', 'run', 'dev'], cwd=frontend_dir,
|
|
shell=True
|
|
)
|
|
PROCESSES.append((5173, proc))
|
|
print(f"[启动] frontend (Vite) -> :5173")
|
|
|
|
# 3. 等待就绪
|
|
print("\n[等待] 等待服务就绪...")
|
|
ok = True
|
|
for port, _ in PROCESSES:
|
|
if wait_port(port):
|
|
print(f" :{port} ✓")
|
|
else:
|
|
print(f" :{port} ✗ 超时!")
|
|
ok = False
|
|
|
|
if not ok:
|
|
print("\n[错误] 部分服务启动失败")
|
|
cleanup()
|
|
sys.exit(1)
|
|
|
|
print(f"\n{'='*50}")
|
|
print("服务就绪:")
|
|
print(f" API: http://localhost:8000/docs")
|
|
print(f" 验证: http://localhost:8001/health")
|
|
if frontend:
|
|
print(f" 前端: http://localhost:5173")
|
|
print(f"\n按 Ctrl+C 停止所有服务")
|
|
print(f"{'='*50}")
|
|
|
|
# 4. 等待退出信号
|
|
try:
|
|
while True:
|
|
time.sleep(1)
|
|
except KeyboardInterrupt:
|
|
pass
|
|
finally:
|
|
cleanup()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|