Files
mp-pilates/deploy-server.sh
2026-04-04 15:39:26 +08:00

213 lines
6.1 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
# ============================================================
# mp-pilates 服务端一键部署脚本
# 流程:本地构建 shared + server → 上传 → 服务器安装依赖 → PM2 重启
# ============================================================
# 部署配置
SERVER_USER="root"
SERVER_HOST="129.204.155.94"
SERVER_PATH="/usr/local/web/mp-pilates-server"
PM2_APP_NAME="mp-pilates-server"
PORT=3008
# 项目根目录(脚本所在位置)
PROJECT_ROOT="$(cd "$(dirname "$0")" && pwd)"
# 颜色输出
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
echo_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
echo_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# 检查 SSH 连接
echo_info "检查服务器连接..."
if ! ssh -o ConnectTimeout=5 ${SERVER_USER}@${SERVER_HOST} "echo '连接成功'" > /dev/null 2>&1; then
echo_error "无法连接到服务器 ${SERVER_HOST}"
echo_warn "请确保:"
echo_warn " 1. 服务器地址正确"
echo_warn " 2. 已配置 SSH 密钥认证或密码"
exit 1
fi
cd "${PROJECT_ROOT}"
# 1. 构建 shared 包server 依赖 shared
echo_info "构建 shared 包..."
pnpm build:shared
if [ $? -ne 0 ]; then
echo_error "shared 构建失败,部署终止"
exit 1
fi
echo_info "shared 构建完成"
# 2. 构建 server 包
echo_info "构建 server 包..."
pnpm build:server
if [ $? -ne 0 ]; then
echo_error "server 构建失败,部署终止"
exit 1
fi
echo_info "server 构建完成"
# 3. 生成 Prisma Client
echo_info "生成 Prisma Client..."
cd packages/server && pnpm prisma:generate && cd "${PROJECT_ROOT}"
if [ $? -ne 0 ]; then
echo_error "Prisma Client 生成失败"
exit 1
fi
echo_info "Prisma Client 生成完成"
# 4. 创建服务器目录
echo_info "准备服务器目录..."
ssh ${SERVER_USER}@${SERVER_HOST} "mkdir -p ${SERVER_PATH}"
# 5. 上传文件到服务器
echo_info "上传文件到服务器 ${SERVER_HOST}:${SERVER_PATH}"
# 上传 server 包含构建产物、prisma、package.json
# 注意:排除 .env 避免覆盖服务器环境配置
rsync -avz --delete \
--exclude 'node_modules' \
--exclude '.git' \
--exclude '.claude' \
--exclude '.env' \
--exclude '.env.local' \
--exclude '.DS_Store' \
--exclude '*.log' \
--exclude 'src' \
--exclude '__tests__' \
--exclude 'test' \
--exclude 'coverage' \
--exclude 'tsconfig*.json' \
--exclude 'nest-cli.json' \
packages/server/ ${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/
if [ $? -ne 0 ]; then
echo_error "server 文件上传失败"
exit 1
fi
# 上传 shared 包构建产物
ssh ${SERVER_USER}@${SERVER_HOST} "mkdir -p ${SERVER_PATH}/../mp-pilates-shared"
rsync -avz --delete \
--exclude 'node_modules' \
--exclude 'src' \
--exclude '.DS_Store' \
packages/shared/ ${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/../mp-pilates-shared/
if [ $? -ne 0 ]; then
echo_error "shared 文件上传失败"
exit 1
fi
# 上传本地 Prisma Client已生成好的避免服务器上版本不一致
echo_info "上传 Prisma Client..."
PRISMA_CLIENT_PATH="$(cd packages/server && node -e "console.log(require.resolve('@prisma/client/../../'))" 2>/dev/null)"
PRISMA_ENGINE_PATH="$(cd packages/server && node -e "console.log(require.resolve('@prisma/engines/../../'))" 2>/dev/null)"
echo_info "文件上传完成"
# 6. 服务器端安装依赖并重启
echo_info "服务器部署操作..."
ssh ${SERVER_USER}@${SERVER_HOST} "bash -l" << 'ENDSSH'
export PATH="$HOME/.nvm/versions/node/v22.17.1/bin:$PATH"
SERVER_PATH="/usr/local/web/mp-pilates-server"
PM2_APP_NAME="mp-pilates-server"
PORT=3008
cd ${SERVER_PATH}
# 检查 .env 是否存在
if [ ! -f .env ]; then
echo "⚠ 未找到 .env 文件,请先创建 ${SERVER_PATH}/.env"
echo " 需要配置: DATABASE_URL, JWT_SECRET, WX_APPID, WX_SECRET 等"
exit 1
fi
# 安装 pnpm如果未安装
if ! command -v pnpm &> /dev/null; then
echo "安装 pnpm..."
npm install -g pnpm
fi
# 设置 npm 镜像
npm config set registry https://registry.npmmirror.com
# 修改 package.json将 workspace:* 替换为实际路径(绕过 workspace 限制)
echo "处理依赖..."
sed -i 's|"@mp-pilates/shared": "workspace:\*"|"@mp-pilates/shared": "file:../mp-pilates-shared"|g' package.json
# 安装生产依赖
echo "安装依赖..."
pnpm install --prod --no-frozen-lockfile
# 确保 shared 包链接正确
echo "链接 shared 包..."
mkdir -p node_modules/@mp-pilates
rm -rf node_modules/@mp-pilates/shared
ln -sf ${SERVER_PATH}/../mp-pilates-shared node_modules/@mp-pilates/shared
# 使用项目本地的 prisma非全局 npx避免版本不一致
echo "生成 Prisma Client..."
./node_modules/.bin/prisma generate 2>/dev/null || npx prisma@5 generate
# 运行数据库迁移(生产环境用 deploy非交互式
echo "运行数据库迁移..."
./node_modules/.bin/prisma migrate deploy 2>/dev/null || npx prisma@5 migrate deploy
# 检查 PM2 是否安装
if ! command -v pm2 &> /dev/null; then
echo "安装 PM2..."
npm install -g pm2
fi
# 停止旧服务(如果存在)
if pm2 describe ${PM2_APP_NAME} &> /dev/null; then
echo "停止旧服务..."
pm2 stop ${PM2_APP_NAME}
pm2 delete ${PM2_APP_NAME}
fi
# 启动新服务
echo "启动服务(端口 ${PORT}..."
PORT=${PORT} pm2 start dist/main.js \
--name ${PM2_APP_NAME} \
--max-memory-restart 512M \
--log-date-format "YYYY-MM-DD HH:mm:ss"
# 保存 PM2 配置
pm2 save --force
# 等待服务启动并检查状态
sleep 3
echo "服务状态:"
pm2 status ${PM2_APP_NAME}
# 检查服务是否在线
if pm2 describe ${PM2_APP_NAME} | grep -q "online"; then
echo "✓ 服务启动成功!"
else
echo "✗ 服务启动失败,查看日志:"
pm2 logs ${PM2_APP_NAME} --lines 30 --nostream
exit 1
fi
ENDSSH
if [ $? -eq 0 ]; then
echo_info "=============================="
echo_info "部署成功!"
echo_info "应用地址: http://${SERVER_HOST}:${PORT}"
echo_info "API 地址: http://${SERVER_HOST}:${PORT}/api"
echo_info "=============================="
else
echo_error "部署失败"
exit 1
fi