#!/bin/bash # # 有声书项目 - 生产环境部署脚本 # 部署到 8.159.134.106:/data/ai/audio # 前端域名: book.rrbrr.com # 后端 API 域名: bookapi.rrbrr.com # 后端端口: 22622 set -e REMOTE_HOST="8.159.134.106" REMOTE_PATH="/data/ai/audio" LOCAL_PROJECT="$(cd "$(dirname "$0")" && pwd)" SSH_KEY="$HOME/.ssh/id_rsa" SSH_PORT="22622" echo "=== 有声书项目 - 生产环境部署 ===" echo "时间: $(date)" echo "主机: $REMOTE_HOST" echo "路径: $REMOTE_PATH" echo "前端: book.rrbrr.com" echo "后端: bookapi.rrbrr.com:22622" echo "" # 1. 构建前端(后端使用已有的 dist) echo "=== 1. 构建前端 ===" cd "$LOCAL_PROJECT/my-uniapp-vue3" npm run build:h5 echo "前端构建完成" cd "$LOCAL_PROJECT" # 2. 同步文件到服务器 echo "" echo "=== 2. 同步文件到服务器 ===" # 创建临时目录 TEMP_DIR="/tmp/deploy_audio_$(date +%Y%m%d_%H%M%S)" ssh -i "$SSH_KEY" -p "$SSH_PORT" root@$REMOTE_HOST "mkdir -p $TEMP_DIR" # 本地临时目录 mkdir -p "$LOCAL_PROJECT/tmp" # 打包后端(使用已有的 dist,打包所有必要文件,排除 node_modules, .git, *.ts) echo "打包后端文件..." cd "$LOCAL_PROJECT/server" tar --exclude='node_modules' --exclude='.git' --exclude='test-*.js' -czf "$LOCAL_PROJECT/tmp/server.tar.gz" . cd "$LOCAL_PROJECT" # 打包前端(只打包 build/h5 目录内容,对接 nginx root) echo "打包前端文件..." cd "$LOCAL_PROJECT/my-uniapp-vue3/dist/build/h5" tar -czf "$LOCAL_PROJECT/tmp/frontend.tar.gz" . cd "$LOCAL_PROJECT" # 上传到服务器 echo "上传后端..." scp -i "$SSH_KEY" -P "$SSH_PORT" "$LOCAL_PROJECT/tmp/server.tar.gz" root@$REMOTE_HOST:$TEMP_DIR/ echo "上传前端..." scp -i "$SSH_KEY" -P "$SSH_PORT" "$LOCAL_PROJECT/tmp/frontend.tar.gz" root@$REMOTE_HOST:$TEMP_DIR/ # 清理本地临时文件 rm -rf "$LOCAL_PROJECT/tmp" # 3. 在服务器上安装 Node.js(如需要) echo "" echo "=== 3. 检查并安装 Node.js ===" ssh -i "$SSH_KEY" -p "$SSH_PORT" root@$REMOTE_HOST << 'ENDSSH' set -e # 检查 Node.js 是否已安装 if ! command -v node &> /dev/null; then echo "安装 Node.js 20.x..." curl -fsSL https://rpm.nodesource.com/setup_20.x | bash - dnf install -y nodejs fi echo "Node.js 版本: $(node --version)" echo "npm 版本: $(npm --version)" ENDSSH # 4. 在服务器上执行部署 echo "" echo "=== 4. 执行服务器部署 ===" ssh -i "$SSH_KEY" -p "$SSH_PORT" root@$REMOTE_HOST << 'ENDSSH' set -e TEMP_DIR=$(ls -td /tmp/deploy_audio_* | head -1) REMOTE_PATH="/data/ai/audio" BACKUP_DIR="$REMOTE_PATH/backup_$(date +%Y%m%d_%H%M%S)" echo "创建备份..." mkdir -p $BACKUP_DIR if [ -d "$REMOTE_PATH/server" ]; then cp -r $REMOTE_PATH/server $BACKUP_DIR/ 2>/dev/null || true fi if [ -d "$REMOTE_PATH/frontend" ]; then cp -r $REMOTE_PATH/frontend $BACKUP_DIR/ 2>/dev/null || true fi echo "解压文件到临时目录..." cd $TEMP_DIR rm -rf server frontend mkdir -p server frontend tar -xzf server.tar.gz -C server/ tar -xzf frontend.tar.gz -C frontend/ echo "部署后端到目标目录..." rm -rf $REMOTE_PATH/server mv server $REMOTE_PATH/ echo "部署前端到 nginx 目录..." rm -rf /data/ai/frontend/build/h5/* mkdir -p /data/ai/frontend/build/h5 cp -r frontend/* /data/ai/frontend/build/h5/ rm -rf frontend echo "验证关键文件..." ls -la $REMOTE_PATH/server/dist/ 2>/dev/null || echo "dist 目录不存在" ls -la $REMOTE_PATH/server/prisma/ 2>/dev/null || echo "prisma 目录不存在" echo "安装后端依赖..." cd $REMOTE_PATH/server npm install --production echo "复制生产环境配置..." cp $REMOTE_PATH/server/.env.production $REMOTE_PATH/server/.env echo "生成 Prisma Client..." npx prisma generate echo "清理临时文件..." rm -rf $TEMP_DIR echo "服务器部署完成!" ENDSSH # 5. 配置 Nginx echo "" echo "=== 5. 配置 Nginx ===" echo "Nginx 配置由宝塔面板管理,请手动配置:" echo "- book.rrbrr.com: /www/server/panel/vhost/nginx/book.rrbrr.com.conf" echo "- bookapi.rrbrr.com: /www/server/panel/vhost/nginx/bookapi.rrbrr.com.conf" echo "后端端口: 3100" # 6. 启动后端服务 echo "" echo "=== 6. 启动后端服务 ===" ssh -i "$SSH_KEY" -p "$SSH_PORT" root@$REMOTE_HOST << 'ENDSSH' set -e cd /data/ai/audio/server # 安装 PM2(如果没有) if ! command -v pm2 &> /dev/null; then echo "安装 PM2..." npm install -g pm2 fi # 停止旧服务 pm2 delete server 2>/dev/null || true # 设置环境变量(使用 3100 端口,避免与 SSH 22622 冲突) export SERVER_PORT=3100 # 启动服务 pm2 start dist/app.js --name server --env production # 保存并设置开机启动 pm2 save pm2 startup echo "后端服务已启动 (端口 22622)!" ENDSSH echo "" echo "=== 部署完成 ===" echo "前端地址: http://book.rrbrr.com" echo "后端 API: http://bookapi.rrbrr.com/api" echo "健康检查: http://bookapi.rrbrr.com/health"