Files

248 lines
7.7 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
# 检查并清理之前的进程
print_message $BLUE "🧹 检查并清理之前的进程..."
if [ -f ".backend.pid" ]; then
OLD_BACKEND_PID=$(cat .backend.pid)
if ps -p $OLD_BACKEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⚠️ 发现已存在的后端进程 $OLD_BACKEND_PID,正在停止..."
kill $OLD_BACKEND_PID 2>/dev/null || true
sleep 2
# 等待进程终止
attempts=0
while ps -p $OLD_BACKEND_PID > /dev/null 2>&1 && [ $attempts -lt 10 ]; do
sleep 1
attempts=$((attempts + 1))
done
# 如果仍未终止,强制杀死
if ps -p $OLD_BACKEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⏳ 强制终止后端进程..."
kill -9 $OLD_BACKEND_PID 2>/dev/null || true
fi
fi
rm -f .backend.pid
fi
if [ -f ".frontend.pid" ]; then
OLD_FRONTEND_PID=$(cat .frontend.pid)
if ps -p $OLD_FRONTEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⚠️ 发现已存在的前端进程 $OLD_FRONTEND_PID,正在停止..."
kill $OLD_FRONTEND_PID 2>/dev/null || true
sleep 2
# 等待进程终止
attempts=0
while ps -p $OLD_FRONTEND_PID > /dev/null 2>&1 && [ $attempts -lt 10 ]; do
sleep 1
attempts=$((attempts + 1))
done
# 如果仍未终止,强制杀死
if ps -p $OLD_FRONTEND_PID > /dev/null 2>&1; then
print_message $YELLOW "⏳ 强制终止前端进程..."
kill -9 $OLD_FRONTEND_PID 2>/dev/null || true
fi
fi
rm -f .frontend.pid
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
print_message $BLUE "📡 启动后端服务 (端口: $BACKEND_PORT)..."
print_message $YELLOW "ℹ️ 后端日志将直接显示在当前终端..."
cd backend
# 启动后端服务(前台模式,直接显示日志)
if command -v uvicorn &> /dev/null; then
print_message $GREEN "✅ 后端启动命令: uvicorn main:app --host 0.0.0.0 --port $BACKEND_PORT --log-level info --reload"
echo ""
echo "========== 后端日志开始 =========="
uvicorn main:app --host 0.0.0.0 --port $BACKEND_PORT --log-level info --reload
else
# 如果uvicorn不在PATH中,使用虚拟环境中的
echo "========== 后端日志开始 =========="
../backend/venv/bin/uvicorn main:app --host 0.0.0.0 --port $BACKEND_PORT --log-level info --reload
fi