#!/usr/bin/env bash set -euo pipefail # ═══════════════════════════════════════════════════════════ # 全国记者站管理系统 — 一键部署脚本 # 用法: ./deploy.sh # 功能: 拉取最新代码 → 安装依赖 → 数据库迁移 → 构建 → 重启服务 # ═══════════════════════════════════════════════════════════ # ── 配置 ────────────────────────────────────────────────── DEPLOY_DIR="/var/www/rsms" GIT_REMOTE="origin" BRANCH="main" API_PORT="${API_PORT:-8787}" PM2_NAME="rsms-server" NGINX_SITE="r.all8ai.top" # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "${GREEN}[deploy]${NC} $1"; } warn() { echo -e "${YELLOW}[warn]${NC} $1"; } err() { echo -e "${RED}[error]${NC} $1"; exit 1; } # ── 前置检查 ────────────────────────────────────────────── check_deps() { log "检查依赖..." command -v git >/dev/null || err "git 未安装" command -v node >/dev/null || err "node 未安装" command -v npm >/dev/null || err "npm 未安装" command -v nginx >/dev/null || err "nginx 未安装" command -v pm2 >/dev/null || err "pm2 未安装 (运行: npm install -g pm2)" NODE_MAJOR=$(node -v | sed 's/v\([0-9]*\).*/\1/') [ "$NODE_MAJOR" -ge 22 ] || err "Node.js 版本需 >= 22 (当前: $(node -v))" log "依赖检查通过: node $(node -v), npm $(npm -v)" } # ── 拉取最新代码 ────────────────────────────────────────── pull_code() { log "拉取最新代码..." cd "$DEPLOY_DIR" git fetch "$GIT_REMOTE" "$BRANCH" git reset --hard "$GIT_REMOTE/$BRANCH" log "代码已更新到 $(git log --oneline -1)" } # ── 安装依赖 ────────────────────────────────────────────── install_deps() { log "安装依赖..." npm install --production=false log "依赖安装完成" } # ── 数据库迁移 ──────────────────────────────────────────── run_migrations() { log "执行数据库迁移..." npm run db:migrate log "数据库迁移完成" } # ── 构建前端 ────────────────────────────────────────────── build_frontend() { log "构建前端..." npm run build log "前端构建完成: $(ls dist/assets/*.js | wc -l) 个 JS 文件" } # ── 重启后端服务 ────────────────────────────────────────── restart_server() { log "重启后端服务 (pm2: $PM2_NAME)..." pm2 delete "$PM2_NAME" 2>/dev/null || true pm2 start npm --name "$PM2_NAME" -- run server:start pm2 save sleep 2 # 健康检查 local health health=$(curl -s "http://127.0.0.1:${API_PORT}/api/health" 2>/dev/null || echo "FAIL") if echo "$health" | grep -q '"status":"ok"'; then log "后端服务健康检查通过" else warn "后端健康检查异常: $health" warn "查看日志: pm2 logs $PM2_NAME --lines 20" fi } # ── 重载 nginx ──────────────────────────────────────────── reload_nginx() { log "检查 nginx 配置..." nginx -t 2>&1 || err "nginx 配置检查失败" nginx -s reload log "nginx 已重载" } # ── 验证站点 ────────────────────────────────────────────── verify_site() { log "验证站点..." local http_code http_code=$(curl -s -o /dev/null -w "%{http_code}" "http://${NGINX_SITE}/" 2>/dev/null || echo "000") if [ "$http_code" = "200" ]; then log "站点验证通过: http://${NGINX_SITE} → 200" else warn "站点返回: $http_code (可能需要检查 DNS 或 nginx 配置)" fi # HTTPS 检查(如果证书存在) if [ -d "/etc/letsencrypt/live/${NGINX_SITE}" ]; then local https_code https_code=$(curl -s -o /dev/null -w "%{http_code}" "https://${NGINX_SITE}/" 2>/dev/null || echo "000") log "HTTPS 验证: https://${NGINX_SITE} → $https_code" fi } # ── 主流程 ──────────────────────────────────────────────── main() { echo "" echo "══════════════════════════════════════════════════" echo " 全国记者站管理系统 — 一键部署" echo "══════════════════════════════════════════════════" echo "" check_deps pull_code install_deps run_migrations build_frontend restart_server reload_nginx verify_site echo "" log "部署完成!" echo " 站点: https://${NGINX_SITE}" echo " API: https://${NGINX_SITE}/api/health" echo " 日志: pm2 logs ${PM2_NAME}" echo " 状态: pm2 list" echo "" } main "$@"