Files

311 lines
9.6 KiB
Bash
Executable File
Raw Permalink 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.
#!/bin/bash
# 开发模式启动脚本 - 前台启动前后端应用(带实时日志)
# 作者: Qwen Assistant
# 功能: 在前台启动后端和前端,直接在终端显示实时日志,并提供日志文件备份
set -e # 遌输错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 打印带颜色的消息
print_message() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# 检查端口是否被占用
check_port() {
local port=$1
if lsof -i :$port > /dev/null 2>&1; then
return 0 # 端口被占用
else
return 1 # 端口未被占用
fi
}
# 生成随机可用端口
get_available_port() {
local start_port=$1
local max_attempts=50
local port=$start_port
local attempts=0
while check_port $port && [ $attempts -lt $max_attempts ]; do
port=$((port + 1))
attempts=$((attempts + 1))
done
if [ $attempts -eq $max_attempts ]; then
print_message $RED "❌ 无法找到可用端口,请手动释放相关端口"
exit 1
fi
echo $port
}
print_message $BLUE "🚀 开始启动 WordMaster Pro 系统 (开发模式 - 实时日志)..."
# 获取脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# 加载环境变量
if [ -f ".env" ]; then
print_message $BLUE "🔧 加载环境变量配置..."
export $(grep -v '^#' .env | xargs)
BACKEND_PORT=${BACKEND_PORT:-8888}
FRONTEND_PORT=${FRONTEND_PORT:-3008}
DATABASE_URL=${DATABASE_URL:-"sqlite:///./wordmaster.db"}
else
print_message $YELLOW "⚠️ 未找到 .env 文件,使用默认配置"
BACKEND_PORT=8888
FRONTEND_PORT=3008
DATABASE_URL="sqlite:///./wordmaster.db"
fi
print_message $BLUE "🔧 使用配置信息:"
print_message $GREEN " 后端端口: $BACKEND_PORT"
print_message $GREEN " 前端端口: $FRONTEND_PORT"
print_message $GREEN " 数据库: $DATABASE_URL"
# 检查端口占用情况
print_message $BLUE "🔍 检查端口占用情况..."
if check_port $BACKEND_PORT; then
print_message $YELLOW "⚠️ 后端端口 $BACKEND_PORT 被占用,寻找可用端口..."
BACKEND_PORT=$(get_available_port 8888)
print_message $GREEN "ℹ️ 使用后端端口: $BACKEND_PORT"
fi
if check_port $FRONTEND_PORT; then
print_message $YELLOW "⚠️ 前端端口 $FRONTEND_PORT 被占用,寻找可用端口..."
FRONTEND_PORT=$(get_available_port 3008)
print_message $GREEN "ℹ️ 使用前端端口: $FRONTEND_PORT"
fi
# 检查依赖状态
check_dependencies() {
local missing_deps=()
# 检查 Python 依赖
if ! command -v python3 &> /dev/null; then
missing_deps+=("python3")
else
if ! python3 -c "import fastapi, uvicorn, sqlalchemy, pydantic, jwt, bcrypt, pandas, fitz, dotenv" > /dev/null 2>&1; then
missing_deps+=("python_backend_deps")
fi
fi
# 检查 Node.js 依赖
if ! command -v node &> /dev/null; then
missing_deps+=("nodejs")
fi
if ! command -v npm &> /dev/null; then
missing_deps+=("npm")
fi
# 检查前端依赖
if [ -f "frontend/package.json" ] && [ ! -d "frontend/node_modules" ]; then
missing_deps+=("frontend_deps")
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
print_message $YELLOW "⚠️ 检测到以下依赖缺失或未安装:"
for dep in "${missing_deps[@]}"; do
echo " - $dep"
done
return 1
fi
return 0
}
print_message $BLUE "🔍 检查依赖安装状态..."
if ! check_dependencies; then
print_message $YELLOW "⚠️ 检测到依赖缺失,正在尝试自动安装..."
# 检查并创建后端虚拟环境
if [ ! -d "backend/venv" ]; then
print_message $BLUE "🔧 创建后端虚拟环境..."
python3 -m venv backend/venv
print_message $GREEN "✅ 虚拟环境创建成功"
fi
# 激活虚拟环境
source backend/venv/bin/activate
# 检查并安装后端依赖
if ! python -c "import fastapi, uvicorn, sqlalchemy, pydantic, jwt, bcrypt, pandas, fitz, dotenv" > /dev/null 2>&1; then
print_message $BLUE "🔧 安装后端依赖..."
cd backend
if [ ! -f "requirements.txt" ]; then
print_message $RED "❌ requirements.txt 不存在"
exit 1
fi
pip install --upgrade pip
if ! pip install -r requirements.txt; then
print_message $RED "❌ 后端依赖安装失败"
exit 1
fi
cd ..
print_message $GREEN "✅ 后端依赖安装完成"
fi
# 检查并安装前端依赖
if [ -f "frontend/package.json" ] && [ ! -d "frontend/node_modules" ]; then
print_message $BLUE "🔧 安装前端依赖..."
cd frontend
if ! npm install; then
print_message $RED "❌ 前端依赖安装失败"
exit 1
fi
cd ..
print_message $GREEN "✅ 前端依赖安装完成"
fi
else
print_message $GREEN "✅ 依赖检查通过"
fi
# 激活后端虚拟环境
print_message $BLUE "🔧 激活后端虚拟环境..."
source backend/venv/bin/activate
# 确保 uploads/images 目录存在
if [ ! -d "backend/uploads/images" ]; then
mkdir -p "backend/uploads/images"
print_message $GREEN "✅ 创建了 uploads/images 目录"
fi
# 设置日志文件路径
BACKEND_LOG="backend/backend_dev.log"
FRONTEND_LOG="frontend/frontend_dev.log"
print_message $BLUE "📡 启动后端服务 (端口: $BACKEND_PORT)..."
print_message $YELLOW "ℹ️ 后端日志将直接显示在当前终端..."
# 启动后端服务(通过管道同时显示和记录日志)
cd backend
# 函数:启动后端服务
start_backend() {
print_message $GREEN "✅ 后端启动命令: uvicorn main:app --host 0.0.0.0 --port $BACKEND_PORT --log-level info --reload"
echo "========== 后端实时日志开始 =========="
# 清理旧日志文件
[ -f "$BACKEND_LOG" ] && rm "$BACKEND_LOG"
# 启动后端并记录日志
uvicorn main:app --host 0.0.0.0 --port $BACKEND_PORT --log-level info --reload 2>&1 | tee -a "$BACKEND_LOG" &
BACKEND_PID=$!
echo $BACKEND_PID > ../.backend.pid
print_message $GREEN "✅ 后端已启动 (PID: $BACKEND_PID, 端口: $BACKEND_PORT)"
# 后端启动后等待几秒让服务就绪
sleep 3
# 检查后端是否启动成功
if ! kill -0 $BACKEND_PID 2>/dev/null; then
print_message $RED "❌ 后端启动失败"
exit 1
fi
print_message $GREEN "✅ 后端服务已就绪"
}
# 启动前端服务(在后台)
start_frontend() {
print_message $BLUE "🎨 启动前端服务 (端口: $FRONTEND_PORT)..."
cd ../frontend
# 创建 .env.development 如果不存在,确保端口配置正确
if [ -f ".env.development" ]; then
# 更新 .env.development with the correct backend port
sed -i.bak "s|VITE_BACKEND_PORT=.*|VITE_BACKEND_PORT=$BACKEND_PORT|" .env.development 2>/dev/null || true
sed -i.bak "s|VITE_SERVER_PORT=.*|VITE_SERVER_PORT=$FRONTEND_PORT|" .env.development 2>/dev/null || true
else
# Create .env.development if it doesn't exist
cat > .env.development << EOF
# 开发环境配置
NODE_ENV=development
VITE_MODE=development
# API配置 - 开发环境使用代理
VITE_API_BASE_URL=/api
VITE_FILE_BASE_URL=/api
VITE_WS_BASE_URL=ws://localhost:$BACKEND_PORT/ws
# 后端服务地址 (仅用于代理配置)
VITE_BACKEND_HOST=localhost
VITE_BACKEND_PORT=$BACKEND_PORT
# 调试配置
VITE_DEBUG=true
VITE_LOG_LEVEL=info
VITE_SERVER_PORT=$FRONTEND_PORT
EOF
print_message $GREEN "✅ 创建了前端环境配置文件"
fi
# 清理旧日志文件
[ -f "$FRONTEND_LOG" ] && rm "$FRONTEND_LOG"
# 启动前端
print_message $GREEN "✅ 前端启动命令: npm run dev -- --port $FRONTEND_PORT"
echo "========== 前端实时日志开始 =========="
npm run dev -- --port $FRONTEND_PORT 2>&1 | tee -a "$FRONTEND_LOG" &
FRONTEND_PID=$!
echo $FRONTEND_PID > ../.frontend.pid
print_message $GREEN "✅ 前端已启动 (PID: $FRONTEND_PID, 端口: $FRONTEND_PORT)"
}
# 启动后端
start_backend
# 启动前端
start_frontend
# 显示完成信息
print_message $GREEN ""
print_message $GREEN "🎉 WordMaster Pro 系统启动成功!(开发模式)"
print_message $GREEN ""
echo ""
print_message $BLUE "📝 访问地址:"
print_message $GREEN "📖 前端访问地址: http://localhost:$FRONTEND_PORT"
print_message $GREEN "🔧 后端 API 地址: http://localhost:$BACKEND_PORT"
print_message $GREEN "📚 API 文档: http://localhost:$BACKEND_PORT/docs"
echo ""
print_message $BLUE "📋 进程信息:"
print_message $GREEN "📡 后端进程 PID: $(cat .backend.pid)"
print_message $GREEN "🎨 前端进程 PID: $(cat .frontend.pid)"
echo ""
print_message $BLUE "📁 实时日志文件 (同时输出到终端):"
print_message $CYAN " 后端日志: $(pwd)/$BACKEND_LOG"
print_message $CYAN " 前端日志: $(pwd)/$FRONTEND_LOG"
echo ""
print_message $YELLOW "💡 提示:"
print_message $YELLOW " - 实时日志已显示在当前终端"
print_message $YELLOW " - 使用 Ctrl+C 停止应用程序"
print_message $YELLOW " - 日志也同时保存到上述文件中"
# 等待用户中断
print_message $GREEN "✅ 服务正在前台运行,实时日志可见..."
trap "print_message $YELLOW '🛑 正在停止服务...'; kill $(cat .backend.pid) 2>/dev/null; kill $(cat .frontend.pid) 2>/dev/null; rm -f .backend.pid .frontend.pid; exit 0" INT
# 等待后台进程
wait