Files
YG_FT_Platform/start_all.py
WIN-JHFT4D3SIVT\caoxiaozhu 40ca89fad5 1. 修改了应用端口的问题
2. 增加了创建虚拟环境的脚本和删除虚拟环境的脚本
2026-01-26 14:33:00 +08:00

305 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
YG_FT_Base 统一启动脚本
同时启动后端 API 服务和 Web 静态服务器
使用方法:
python start_all.py start # 启动所有服务
python start_all.py stop # 停止所有服务
python start_all.py restart # 重启所有服务
python start_all.py status # 查看服务状态
"""
import os
import sys
import yaml
import signal
import subprocess
import time
from pathlib import Path
# 获取脚本所在目录
SCRIPT_DIR = Path(__file__).parent.absolute()
CONFIG_FILE = SCRIPT_DIR / "config.yaml"
WEB_DIR = SCRIPT_DIR / "web"
# PID 文件路径
API_PID_FILE = SCRIPT_DIR / ".api.pid"
WEB_PID_FILE = SCRIPT_DIR / ".web.pid"
def load_config():
"""加载配置文件"""
if not CONFIG_FILE.exists():
print(f"❌ 配置文件不存在: {CONFIG_FILE}")
sys.exit(1)
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
app_config = config.get('app', {})
return {
'api_port': app_config.get('port', 7861),
'web_port': app_config.get('web_port', 7862)
}
def is_port_in_use(port):
"""检查端口是否被占用"""
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
return s.connect_ex(('localhost', port)) == 0
def get_pid(pid_file):
"""获取 PID"""
if pid_file.exists():
try:
return int(pid_file.read_text().strip())
except:
return None
return None
def is_process_running(pid):
"""检查进程是否在运行"""
try:
os.kill(pid, 0)
return True
except OSError:
return False
def kill_process(pid_file):
"""杀死进程"""
pid = get_pid(pid_file)
if pid and is_process_running(pid):
try:
os.kill(pid, signal.SIGTERM)
time.sleep(0.5)
# 如果还在运行,强制杀死
if is_process_running(pid):
os.kill(pid, signal.SIGKILL)
return True
except OSError:
pass
pid_file.unlink(missing_ok=True)
return False
def check_virtual_env():
"""检查虚拟环境是否存在"""
venv_path = SCRIPT_DIR / "B_venv"
if not venv_path.exists():
print("⚠️ 虚拟环境不存在,请先运行 create_venv.sh 创建")
return False
return True
def start_api():
"""启动后端 API 服务"""
config = load_config()
api_port = config['api_port']
print("🚀 启动后端 API 服务...")
if not check_virtual_env():
return False
if is_port_in_use(api_port):
print(f"❌ 端口 {api_port} 已被占用,后端服务可能已在运行")
return False
venv_python = SCRIPT_DIR / "B_venv" / "bin" / "python"
main_py = SCRIPT_DIR / "src" / "main.py"
if not venv_python.exists():
venv_python = SCRIPT_DIR / "B_venv" / "Scripts" / "python.exe" # Windows
if not main_py.exists():
print(f"❌ 找不到主程序文件: {main_py}")
return False
# 启动进程
env = os.environ.copy()
env['PYTHONUNBUFFERED'] = '1'
proc = subprocess.Popen(
[str(venv_python), str(main_py)],
cwd=str(SCRIPT_DIR),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
env=env
)
# 写入 PID
with open(API_PID_FILE, 'w') as f:
f.write(str(proc.pid))
# 等待服务启动
time.sleep(2)
if proc.poll() is not None:
print("❌ 后端服务启动失败")
API_PID_FILE.unlink(missing_ok=True)
return False
print(f"✅ 后端服务已启动 (PID: {proc.pid}, 端口: {api_port})")
return True
def start_web():
"""启动 Web 静态服务器"""
config = load_config()
web_port = config['web_port']
print("🚀 启动 Web 静态服务器...")
# 从项目根目录启动,这样 /lib/... 路径可以正确映射到 $PROJECT/lib/...
web_root = SCRIPT_DIR
if not web_root.exists():
print(f"❌ Web 目录不存在: {web_root}")
return False
if is_port_in_use(web_port):
print(f"⚠️ 端口 {web_port} 已被占用Web 服务可能已在运行")
return False
# 使用 python 启动简单 HTTP 服务器(从项目根目录)
env = os.environ.copy()
env['PYTHONUNBUFFERED'] = '1'
proc = subprocess.Popen(
[sys.executable, '-m', 'http.server', str(web_port)],
cwd=str(web_root),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
env=env
)
# 写入 PID
with open(WEB_PID_FILE, 'w') as f:
f.write(str(proc.pid))
time.sleep(1)
if proc.poll() is not None:
print("❌ Web 服务启动失败")
WEB_PID_FILE.unlink(missing_ok=True)
return False
print(f"✅ Web 服务已启动 (PID: {proc.pid}, 端口: {web_port})")
return True
def stop_all():
"""停止所有服务"""
print("🛑 停止所有服务...")
# 停止后端服务
if kill_process(API_PID_FILE):
print("✅ 后端服务已停止")
# 停止 Web 服务
if kill_process(WEB_PID_FILE):
print("✅ Web 服务已停止")
# 清理残留进程
subprocess.run(['pkill', '-f', 'src/main.py'], capture_output=True)
config = load_config()
subprocess.run(['pkill', '-f', f'http.server {config["web_port"]}'], capture_output=True)
def show_status():
"""显示服务状态"""
config = load_config()
api_port = config['api_port']
web_port = config['web_port']
print("\n📊 服务状态:")
print("-" * 40)
api_pid = get_pid(API_PID_FILE)
if api_pid and is_process_running(api_pid):
print(f"✅ 后端 API: 运行中 (PID: {api_pid}, 端口: {api_port})")
else:
print(f"❌ 后端 API: 未运行 (端口: {api_port})")
web_pid = get_pid(WEB_PID_FILE)
if web_pid and is_process_running(web_pid):
print(f"✅ Web 服务: 运行中 (PID: {web_pid}, 端口: {web_port})")
else:
print(f"❌ Web 服务: 未运行 (端口: {web_port})")
print("-" * 40)
print("\n🌐 访问地址:")
print(f" - 后端 API: http://localhost:{api_port}")
print(f" - Web 页面: http://localhost:{web_port}/web/pages/main.html")
print()
def main():
if len(sys.argv) < 2:
print("用法: python start_all.py {start|stop|restart|status}")
print()
print("命令:")
print(" start - 启动所有服务")
print(" stop - 停止所有服务")
print(" restart - 重启所有服务")
print(" status - 查看服务状态")
sys.exit(1)
command = sys.argv[1].lower()
print("====================================")
print("YG_FT_Base 统一启动脚本 (Python版)")
print("====================================")
print()
config = load_config()
print(f"📦 端口配置:")
print(f" - 后端 API: {config['api_port']}")
print(f" - Web 服务: {config['web_port']}")
print()
if command == 'start':
start_api()
start_web()
print()
print("====================================")
print("所有服务已启动!")
print("====================================")
show_status()
elif command == 'stop':
stop_all()
print("✅ 所有服务已停止")
elif command == 'restart':
stop_all()
time.sleep(1)
start_api()
start_web()
print()
print("====================================")
print("所有服务已重启!")
print("====================================")
show_status()
elif command == 'status':
show_status()
else:
print(f"❌ 未知命令: {command}")
print("用法: python start_all.py {start|stop|restart|status}")
sys.exit(1)
if __name__ == '__main__':
main()