248 lines
7.7 KiB
Bash
Executable File
248 lines
7.7 KiB
Bash
Executable File
#!/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 |