#!/bin/bash # 情绪博物馆项目打包脚本 # 作者: EmotionMuseum Team # 版本: 2.0.0 # 更新: 适配新的部署脚本和文件结构 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_step() { echo -e "${BLUE}[STEP]${NC} $1" } # 项目信息 PROJECT_NAME="emotion-museum" VERSION="1.0.0" BUILD_TIME=$(date +"%Y%m%d_%H%M%S") PACKAGE_NAME="${PROJECT_NAME}-${VERSION}-${BUILD_TIME}" # 创建打包目录 PACKAGE_DIR="packages/${PACKAGE_NAME}" TEMP_DIR="temp_build" # 清理函数 cleanup() { log_info "清理临时文件..." rm -rf "$TEMP_DIR" } # 设置清理陷阱 trap cleanup EXIT # 检查环境 check_environment() { log_step "检查构建环境..." # 检查Node.js if ! command -v node &> /dev/null; then log_error "Node.js未安装,请先安装Node.js" exit 1 fi log_info "Node.js版本: $(node --version)" # 检查npm if ! command -v npm &> /dev/null; then log_error "npm未安装,请先安装npm" exit 1 fi log_info "npm版本: $(npm --version)" # 检查Java if ! command -v java &> /dev/null; then log_error "Java未安装,请先安装Java 17+" exit 1 fi log_info "Java版本: $(java --version | head -n 1)" # 检查Maven if ! command -v mvn &> /dev/null; then log_error "Maven未安装,请先安装Maven" exit 1 fi log_info "Maven版本: $(mvn --version | head -n 1)" } # 构建前端 build_frontend() { log_step "构建前端项目..." # 检查前端目录 if [ ! -d "web" ]; then log_warn "web目录不存在,跳过前端构建" log_info "注意:将使用预构建的前端文件" return fi cd web # 检查package.json if [ ! -f "package.json" ]; then log_warn "package.json不存在,跳过前端构建" cd .. return fi # 安装依赖 log_info "安装前端依赖..." npm ci # 构建生产版本 log_info "构建前端生产版本..." npm run build:prod || npm run build # 检查构建结果 if [ ! -d "dist" ]; then log_error "前端构建失败,dist目录不存在" exit 1 fi log_info "前端构建完成" cd .. } # 构建后端 build_backend() { log_step "构建后端项目..." # 检查后端目录 if [ ! -d "backend" ]; then log_warn "backend目录不存在,跳过后端构建" log_info "注意:将使用预构建的JAR文件" return fi # 检查是否有源码目录结构 if [ ! -f "backend/pom.xml" ]; then log_warn "backend/pom.xml不存在,跳过后端构建" log_info "注意:将使用预构建的JAR文件" return fi cd backend # 清理之前的构建 log_info "清理之前的构建..." mvn clean # 编译和打包 log_info "编译和打包后端服务..." mvn package -DskipTests # 检查构建结果 local services=("emotion-gateway" "emotion-ai" "emotion-user") for service in "${services[@]}"; do if [ ! -f "${service}/target/${service}-${VERSION}.jar" ]; then log_error "后端服务 ${service} 构建失败" exit 1 fi done log_info "后端构建完成" cd .. } # 创建部署包 create_package() { log_step "创建部署包..." # 创建打包目录 mkdir -p "$PACKAGE_DIR" mkdir -p "$TEMP_DIR" # 复制前端文件 log_info "打包前端文件..." mkdir -p "$TEMP_DIR/frontend" # 如果有构建产物,复制dist目录 if [ -d "web/dist" ]; then cp -r web/dist/* "$TEMP_DIR/frontend/" fi # 复制前端相关文件 if [ -f "web/Dockerfile" ]; then cp web/Dockerfile "$TEMP_DIR/frontend/" fi if [ -f "web/nginx.conf" ]; then cp web/nginx.conf "$TEMP_DIR/frontend/" fi # 复制前端配置文件 mkdir -p "$TEMP_DIR/frontend/config" cp web/config/* "$TEMP_DIR/frontend/config/" 2>/dev/null || true cp web/.env* "$TEMP_DIR/frontend/" 2>/dev/null || true # 如果没有web目录,从packages目录复制预构建的前端文件 if [ ! -d "web" ] && [ -d "packages/emotion-museum-*/frontend" ]; then log_info "使用预构建的前端文件..." cp -r packages/emotion-museum-*/frontend/* "$TEMP_DIR/frontend/" fi # 复制后端文件 log_info "打包后端文件..." mkdir -p "$TEMP_DIR/backend" # 如果有构建产物,复制jar文件 if [ -d "backend" ] && [ -f "backend/pom.xml" ]; then # 从构建目录复制 cp backend/emotion-gateway/target/emotion-gateway-*.jar "$TEMP_DIR/backend/" 2>/dev/null || true cp backend/emotion-ai/target/emotion-ai-*.jar "$TEMP_DIR/backend/" 2>/dev/null || true cp backend/emotion-user/target/emotion-user-*.jar "$TEMP_DIR/backend/" 2>/dev/null || true # 复制Dockerfile cp backend/emotion-gateway/Dockerfile "$TEMP_DIR/backend/gateway-Dockerfile" 2>/dev/null || true cp backend/emotion-ai/Dockerfile "$TEMP_DIR/backend/ai-Dockerfile" 2>/dev/null || true cp backend/emotion-user/Dockerfile "$TEMP_DIR/backend/user-Dockerfile" 2>/dev/null || true else # 从packages目录复制预构建的文件 if [ -d "packages/emotion-museum-*/backend" ]; then log_info "使用预构建的后端文件..." cp packages/emotion-museum-*/backend/*.jar "$TEMP_DIR/backend/" 2>/dev/null || true cp packages/emotion-museum-*/backend/*-Dockerfile "$TEMP_DIR/backend/" 2>/dev/null || true fi fi # 复制配置文件 mkdir -p "$TEMP_DIR/backend/config" if [ -d "backend" ] && [ -f "backend/pom.xml" ]; then # 从源码目录复制 cp backend/emotion-gateway/src/main/resources/application*.yml "$TEMP_DIR/backend/config/" 2>/dev/null || true cp backend/emotion-ai/src/main/resources/application*.yml "$TEMP_DIR/backend/config/" 2>/dev/null || true cp backend/emotion-user/src/main/resources/application*.yml "$TEMP_DIR/backend/config/" 2>/dev/null || true else # 从packages目录复制 if [ -d "packages/emotion-museum-*/backend/config" ]; then cp packages/emotion-museum-*/backend/config/* "$TEMP_DIR/backend/config/" 2>/dev/null || true fi fi # 复制数据库脚本 log_info "打包数据库脚本..." mkdir -p "$TEMP_DIR/database" # 优先从backend目录复制,然后从packages目录复制 if [ -f "backend/mysql_emotion_museum_final.sql" ]; then cp backend/mysql_emotion_museum_final.sql "$TEMP_DIR/database/" elif [ -f "packages/emotion-museum-*/database/mysql_emotion_museum_final.sql" ]; then cp packages/emotion-museum-*/database/mysql_emotion_museum_final.sql "$TEMP_DIR/database/" fi if [ -f "backend/verify-database-script.sql" ]; then cp backend/verify-database-script.sql "$TEMP_DIR/database/" elif [ -f "packages/emotion-museum-*/database/verify-database-script.sql" ]; then cp packages/emotion-museum-*/database/verify-database-script.sql "$TEMP_DIR/database/" fi # 复制部署配置和脚本 log_info "打包部署配置..." # 复制部署配置目录 if [ -d "deploy" ]; then cp -r deploy "$TEMP_DIR/" elif [ -d "packages/emotion-museum-*/deploy" ]; then cp -r packages/emotion-museum-*/deploy "$TEMP_DIR/" fi # 复制Docker Compose文件 cp docker-compose*.yml "$TEMP_DIR/" 2>/dev/null || true if [ -d "packages/emotion-museum-*" ]; then cp packages/emotion-museum-*/docker-compose*.yml "$TEMP_DIR/" 2>/dev/null || true fi # 复制部署脚本 local scripts=("deploy.sh" "install-environment.sh" "init-database.sh" "manage.sh") for script in "${scripts[@]}"; do if [ -f "$script" ]; then cp "$script" "$TEMP_DIR/" elif [ -f "packages/emotion-museum-*/$script" ]; then cp packages/emotion-museum-*/"$script" "$TEMP_DIR/" fi done # 复制文档文件 local docs=("README.md" "DEPLOY.md" "QUICK_START.md") for doc in "${docs[@]}"; do if [ -f "$doc" ]; then cp "$doc" "$TEMP_DIR/" elif [ -f "packages/emotion-museum-*/$doc" ]; then cp packages/emotion-museum-*/"$doc" "$TEMP_DIR/" fi done # 复制环境配置文件 cp .env* "$TEMP_DIR/" 2>/dev/null || true if [ -d "packages/emotion-museum-*" ]; then cp packages/emotion-museum-*/.env* "$TEMP_DIR/" 2>/dev/null || true fi # 如果没有.env文件,创建一个模板 if [ ! -f "$TEMP_DIR/.env.test" ]; then echo "# 请配置环境变量" > "$TEMP_DIR/.env.test" fi # 创建版本信息文件 create_version_info # 创建部署说明 create_deploy_instructions # 移动到最终目录 mv "$TEMP_DIR"/* "$PACKAGE_DIR/" log_info "部署包创建完成: $PACKAGE_DIR" } # 创建版本信息 create_version_info() { log_info "生成版本信息..." cat > "$TEMP_DIR/VERSION.txt" << EOF 情绪博物馆 - 版本信息 ======================== 项目名称: $PROJECT_NAME 版本号: $VERSION 构建时间: $BUILD_TIME 构建环境: $(uname -s) $(uname -m) 前端信息: - Node.js: $(node --version) - npm: $(npm --version) 后端信息: - Java: $(java --version | head -n 1) - Maven: $(mvn --version | head -n 1) Git信息: $(if [ -d ".git" ]; then echo "- 分支: $(git branch --show-current 2>/dev/null || echo 'unknown')" echo "- 提交: $(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')" echo "- 时间: $(git log -1 --format=%cd 2>/dev/null || echo 'unknown')" else echo "- Git信息不可用" fi) 文件清单: - 前端构建产物: frontend/ - 后端JAR文件: backend/ - 数据库脚本: database/ - 部署配置: deploy/ - Docker配置: docker-compose*.yml - 部署脚本: *.sh - 说明文档: *.md EOF } # 创建部署说明 create_deploy_instructions() { log_info "生成部署说明..." cat > "$TEMP_DIR/QUICK_START.md" << 'EOF' # 情绪博物馆测试环境快速部署指南 ## 📦 包内容说明 ``` emotion-museum-1.0.0-YYYYMMDD_HHMMSS/ ├── frontend/ # 前端构建产物 │ ├── assets/ # 静态资源 │ ├── index.html # 主页面 │ ├── Dockerfile # 前端容器配置 │ ├── nginx.conf # Nginx配置 │ └── config/ # 前端配置 ├── backend/ # 后端JAR文件 │ ├── emotion-gateway-*.jar # 网关服务 │ ├── emotion-ai-*.jar # AI服务 │ ├── emotion-user-*.jar # 用户服务 │ ├── config/ # 配置文件 │ │ ├── application-test.yml │ │ ├── gateway-test.yml │ │ └── ai-test.yml │ ├── gateway-Dockerfile # 网关容器配置 │ ├── ai-Dockerfile # AI服务容器配置 │ └── user-Dockerfile # 用户服务容器配置 ├── database/ # 数据库脚本 │ ├── mysql_emotion_museum_final.sql │ └── verify-database-script.sql ├── deploy/ # 部署配置 │ ├── nginx/conf.d/ # Nginx配置 │ ├── mysql/conf.d/ # MySQL配置 │ └── redis/ # Redis配置 ├── docker-compose.yml # 默认配置 ├── docker-compose.test.yml # 测试环境配置 ├── deploy.sh # 主部署脚本 ├── install-environment.sh # 环境安装脚本 ├── init-database.sh # 数据库初始化脚本 ├── manage.sh # 管理脚本(兼容) ├── .env.test # 测试环境变量 ├── README.md # 快速开始指南 ├── VERSION.txt # 版本信息 ├── DEPLOY.md # 详细部署文档 └── QUICK_START.md # 本文件 ``` ## 🚀 快速部署步骤 ### 1. 系统要求 - **操作系统**: Linux/macOS (推荐 Ubuntu 20.04+) - **内存**: 最少4GB,推荐8GB+ - **磁盘**: 最少20GB可用空间 - **网络**: 能够访问互联网 ### 2. 部署步骤 #### 方式一:一键部署(推荐) ```bash # 1. 解压部署包 tar -xzf emotion-museum-*.tar.gz cd emotion-museum-* # 2. 配置环境变量(重要) vim .env.test # 修改 SERVER_IP 为实际IP # 配置 COZE_API_TOKEN # 3. 一键部署(包含环境安装、数据库初始化、服务部署) chmod +x deploy.sh ./deploy.sh ``` #### 方式二:分步部署 ```bash # 1. 解压部署包 tar -xzf emotion-museum-*.tar.gz cd emotion-museum-* # 2. 配置环境变量 vim .env.test # 3. 分步部署 chmod +x deploy.sh ./deploy.sh install-env # 安装环境 ./deploy.sh init-db # 初始化数据库 ./deploy.sh build # 构建镜像 ./deploy.sh start # 启动服务 ``` #### 方式三:跳过某些步骤 ```bash # 如果已安装环境,跳过环境安装 ./deploy.sh --skip-env # 如果已初始化数据库,跳过数据库初始化 ./deploy.sh --skip-db # 启用调试模式 ./deploy.sh --debug ``` ### 3. 验证部署 ```bash # 查看服务状态 ./deploy.sh status # 健康检查 ./deploy.sh health # 查看日志 ./deploy.sh logs ``` ### 4. 访问应用 - **前端应用**: http://localhost (或 http://your-server-ip) - **API网关**: http://localhost:9000 - **Nacos控制台**: http://localhost:8848/nacos (nacos/nacos) ## ⚙️ 配置说明 ### 必须配置项 编辑 `.env.test` 文件中的以下配置: ```bash # 服务器IP(重要:修改为实际IP) SERVER_IP=your-server-ip # Coze API配置(必须) COZE_API_TOKEN=your-actual-coze-api-token # 数据库密码(建议修改) MYSQL_ROOT_PASSWORD=your-secure-password MYSQL_PASSWORD=your-secure-password # JWT密钥(建议修改) JWT_SECRET=your-production-jwt-secret-key ``` ### 可选配置项 ```bash # 时区设置 TZ=Asia/Shanghai # 端口配置 GATEWAY_PORT=9000 USER_SERVICE_PORT=9001 AI_SERVICE_PORT=9002 # 日志和存储路径 LOG_PATH=/data/logs/emotion-museum UPLOAD_PATH=/data/uploads/emotion-museum ``` ## 🛠️ 管理命令 ```bash # 主要部署命令 ./deploy.sh # 完整部署 ./deploy.sh start # 启动服务 ./deploy.sh stop # 停止服务 ./deploy.sh restart # 重启服务 ./deploy.sh status # 查看状态 # 日志管理 ./deploy.sh logs # 查看所有日志 ./deploy.sh logs -f # 跟踪日志 ./deploy.sh logs gateway # 查看网关日志 ./deploy.sh logs ai-service # 查看AI服务日志 # 数据管理 ./deploy.sh backup # 备份数据 ./deploy.sh health # 健康检查 ./deploy.sh clean # 清理资源 # 独立脚本 ./install-environment.sh # 安装环境 ./init-database.sh # 初始化数据库 # 兼容命令(旧版本) ./manage.sh start # 启动服务 ./manage.sh status # 查看状态 ``` ## 🔧 生产环境配置 ### 1. 使用生产配置 ```bash # 使用生产环境配置 docker-compose -f docker-compose.prod.yml up -d ``` ### 2. 配置HTTPS ```bash # 1. 放置SSL证书 cp your-domain.crt deploy/nginx/ssl/emotion-museum.crt cp your-domain.key deploy/nginx/ssl/emotion-museum.key # 2. 修改Nginx配置 vim deploy/nginx/conf.d/emotion-museum.conf # 取消HTTPS相关配置的注释 # 3. 重启Nginx docker-compose restart nginx ``` ### 3. 配置域名 ```bash # 修改Nginx配置中的域名 vim deploy/nginx/conf.d/emotion-museum.conf # 将 localhost 替换为您的域名 ``` ## 🚨 故障排除 ### 常见问题 1. **环境安装失败** ```bash # 检查系统要求 ./install-environment.sh verify # 手动安装特定组件 ./install-environment.sh docker ``` 2. **端口冲突** ```bash # 检查端口占用 netstat -tlnp | grep :80 netstat -tlnp | grep :3306 # 修改 .env.test 中的端口配置 ``` 3. **数据库初始化失败** ```bash # 查看MySQL容器日志 docker logs emotion-mysql # 重新初始化 ./init-database.sh clean ./init-database.sh ``` 4. **服务启动失败** ```bash # 查看服务日志 ./deploy.sh logs service-name # 查看容器状态 docker ps -a ``` 5. **网络连接问题** ```bash # 检查Docker网络 docker network ls # 健康检查 ./deploy.sh health ``` ### 获取帮助 - 查看详细文档: `cat DEPLOY.md` - 查看快速指南: `cat README.md` - 查看版本信息: `cat VERSION.txt` - 查看部署命令: `./deploy.sh --help` ## 📞 技术支持 如遇到问题,请按以下步骤排查: 1. **查看详细日志**:`./deploy.sh logs --debug` 2. **检查服务状态**:`./deploy.sh status` 3. **验证配置文件**:检查 `.env.test` 配置 4. **查看详细文档**:`DEPLOY.md` 5. **重新部署**:`./deploy.sh clean && ./deploy.sh` ## 📝 重要提醒 - ⚠️ **首次部署**:请务必修改 `.env.test` 中的 `SERVER_IP` 和 `COZE_API_TOKEN` - ⚠️ **生产环境**:请修改所有默认密码和密钥 - ⚠️ **防火墙**:确保开放必要的端口 (80, 3306, 6379, 8848, 9000-9002) --- **部署完成后,请及时修改默认密码和敏感配置!** EOF } # 压缩打包 compress_package() { log_step "压缩部署包..." cd packages tar -czf "${PACKAGE_NAME}.tar.gz" "$PACKAGE_NAME" # 计算文件大小和校验和 local size=$(du -h "${PACKAGE_NAME}.tar.gz" | cut -f1) local checksum=$(sha256sum "${PACKAGE_NAME}.tar.gz" | cut -d' ' -f1) log_info "压缩完成:" log_info " 文件: packages/${PACKAGE_NAME}.tar.gz" log_info " 大小: $size" log_info " 校验: $checksum" # 创建校验文件 echo "$checksum ${PACKAGE_NAME}.tar.gz" > "${PACKAGE_NAME}.sha256" cd .. } # 生成部署报告 generate_report() { log_step "生成部署报告..." local report_file="packages/${PACKAGE_NAME}_REPORT.txt" cat > "$report_file" << EOF 情绪博物馆部署包报告 ================== 构建信息: - 包名称: ${PACKAGE_NAME}.tar.gz - 构建时间: $BUILD_TIME - 构建环境: $(uname -s) $(uname -m) 包内容: - 前端构建产物 ✓ - 后端JAR文件 ✓ - 数据库脚本 ✓ - 部署配置 ✓ - Docker配置 ✓ - 管理脚本 ✓ - 说明文档 ✓ 文件信息: - 压缩包大小: $(du -h "packages/${PACKAGE_NAME}.tar.gz" | cut -f1) - SHA256校验: $(cat "packages/${PACKAGE_NAME}.sha256" | cut -d' ' -f1) 部署要求: - Docker 20.10+ - Docker Compose 1.29+ - 内存: 4GB+ - 磁盘: 10GB+ 快速部署: 1. 解压: tar -xzf ${PACKAGE_NAME}.tar.gz 2. 进入: cd ${PACKAGE_NAME} 3. 配置: vim .env 4. 部署: ./quick-deploy.sh 注意事项: - 请配置正确的Coze API Token - 生产环境请修改默认密码 - 建议配置HTTPS证书 - 确保防火墙开放必要端口 技术支持: - 详细文档: DEPLOY.md - 快速指南: QUICK_START.md - 管理命令: ./manage.sh --help EOF log_info "部署报告已生成: $report_file" } # 主函数 main() { echo "📦 开始打包情绪博物馆项目..." echo "" check_environment build_frontend build_backend create_package compress_package generate_report echo "" log_info "🎉 打包完成!" echo "" echo "📁 部署包位置:" echo " packages/${PACKAGE_NAME}.tar.gz" echo "" echo "📋 部署步骤:" echo " 1. 将压缩包上传到服务器" echo " 2. 解压: tar -xzf ${PACKAGE_NAME}.tar.gz" echo " 3. 进入目录: cd ${PACKAGE_NAME}" echo " 4. 配置环境: vim .env" echo " 5. 快速部署: ./quick-deploy.sh" echo "" echo "📖 详细说明请查看包内的 QUICK_START.md 文件" echo "" } # 处理命令行参数 case "${1:-}" in "frontend") check_environment build_frontend ;; "backend") check_environment build_backend ;; "clean") log_info "清理构建文件..." rm -rf packages temp_build rm -rf web/dist web/node_modules cd backend && mvn clean && cd .. log_info "清理完成" ;; *) main ;; esac