#!/usr/bin/env python # -*- coding: utf-8 -*- """ mini-OpenClaw 一键启动脚本(纯 Python) - PyCharm 兼容版 用法: python start.py # 同时启动 后端(FastAPI:8002) + 前端(Next.js:3000) python start.py -b # 只启动后端 python start.py -f # 只启动前端 访问: 前端界面: http://localhost:3000 后端API : http://localhost:8002 (docs: /docs) """ import os import subprocess import sys import time import platform ROOT = os.path.dirname(os.path.abspath(__file__)) BACKEND_DIR = os.path.join(ROOT, "backend") FRONTEND_DIR = ROOT # 检测操作系统 IS_WINDOWS = platform.system() == "Windows" VENV_PY = os.path.join(BACKEND_DIR, "venv", "Scripts", "python.exe") if IS_WINDOWS else os.path.join(BACKEND_DIR, "venv", "bin", "python") def check_port(port): """检查端口是否已被占用""" import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: return s.connect_ex(('localhost', port)) == 0 def run_backend(): """启动 FastAPI 后端(8002)""" print("\n[后端] 正在启动 FastAPI (端口 8002) ...", flush=True) # 检查虚拟环境是否存在 if not os.path.exists(VENV_PY): print(f"❌ 错误: 虚拟环境不存在: {VENV_PY}") print(" 请先运行: cd backend && python -m venv venv && venv\\Scripts\\activate && pip install -r requirements.txt") return None # 检查端口是否已被占用 if check_port(8002): print("⚠️ 警告: 端口 8002 已被占用,后端可能已在运行") return None # 设置环境变量(禁用代理) env = os.environ.copy() env["NO_PROXY"] = "*" env["HTTP_PROXY"] = "" env["HTTPS_PROXY"] = "" cmd = [VENV_PY, "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8002"] if IS_WINDOWS: # Windows: 创建新的控制台窗口 proc = subprocess.Popen(cmd, cwd=BACKEND_DIR, env=env, creationflags=subprocess.CREATE_NEW_CONSOLE) else: # Linux/Mac: 后台运行 proc = subprocess.Popen(cmd, cwd=BACKEND_DIR, env=env) print("✅ 后端启动成功 (PID: {})".format(proc.pid), flush=True) return proc def run_frontend(): """启动 Next.js 前端(3000)""" print("\n[前端] 正在启动 Next.js (端口 3000) ...", flush=True) # 检查 node_modules 是否存在 if not os.path.exists(os.path.join(FRONTEND_DIR, "node_modules")): print("⚠️ 警告: node_modules 不存在,正在安装依赖...") subprocess.run(["npm", "install"], cwd=FRONTEND_DIR, shell=True) # 检查端口是否已被占用 if check_port(3000): print("⚠️ 警告: 端口 3000 已被占用,前端可能已在运行") return None cmd = ["npm", "run", "dev"] if IS_WINDOWS: # Windows: 创建新的控制台窗口 proc = subprocess.Popen(cmd, cwd=FRONTEND_DIR, shell=True, creationflags=subprocess.CREATE_NEW_CONSOLE) else: # Linux/Mac: 后台运行 proc = subprocess.Popen(cmd, cwd=FRONTEND_DIR, shell=True) print("✅ 前端启动成功 (PID: {})".format(proc.pid), flush=True) return proc def main(): args = sys.argv[1:] only_backend = "-b" in args only_frontend = "-f" in args if only_backend: run_backend() print("\n后端已启动: http://localhost:8002 (API文档 /docs)") return if only_frontend: run_frontend() print("\n前端已启动: http://localhost:3000") return # 默认同时启动前后端,各自独立窗口 run_backend() run_frontend() print("\n" + "=" * 50) print(" mini-OpenClaw 已启动!") print(" 前端界面: http://localhost:3000") print(" 后端 API: http://localhost:8002 (docs: /docs)") print(" 每个服务在独立命令行窗口运行,关闭窗口即停服务") print("=" * 50) print("\n本脚本会保持运行(可 Ctrl+C 退出)。想只起一个,用: python start.py -b 或 -f") if __name__ == "__main__": main() # 保持主进程存活 try: while True: time.sleep(60) except KeyboardInterrupt: print("\n已退出启动器。")