Files

131 lines
4.1 KiB
Python
Raw Permalink Normal View History

#!/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已退出启动器。")