#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════════════ # 天工智能体平台 — 增量升级脚本 # 用法: bash upgrade.sh # ═══════════════════════════════════════════════════════════════════════════════ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' info() { echo -e "${GREEN}[✓]${NC} $*"; } warn() { echo -e "${YELLOW}[!]${NC} $*"; } error() { echo -e "${RED}[✗]${NC} $*"; exit 1; } COMPOSE_FILE="./docker-compose.prod.yml" ENV_FILE="./backend/.env" # 验证 if [ ! -f "$COMPOSE_FILE" ]; then error "未找到 $COMPOSE_FILE,请确认当前目录为项目根目录" fi if [ ! -f "$ENV_FILE" ]; then warn "未找到 $ENV_FILE,后端可能无法正常启动" fi if docker compose version &>/dev/null; then COMPOSE="docker compose" elif command -v docker-compose &>/dev/null; then COMPOSE="docker-compose" else error "未找到 Docker Compose" fi echo "" echo -e "${CYAN}╔══════════════════════════════════════╗${NC}" echo -e "${CYAN}║ 天工智能体平台 — 增量升级 ║${NC}" echo -e "${CYAN}╚══════════════════════════════════════╝${NC}" echo "" # ─── 1. 备份当前配置 ───────────────────────────────────────────────────────── BACKUP_DIR="./backups/upgrade-$(date +%Y%m%d-%H%M%S)" mkdir -p "$BACKUP_DIR" if [ -f "$ENV_FILE" ]; then cp "$ENV_FILE" "$BACKUP_DIR/.env.bak" info "已备份 .env 到 $BACKUP_DIR/" fi # 备份数据库(如果 MySQL 容器正在运行) if docker ps --format '{{.Names}}' | grep -q "aiagent-mysql"; then echo "正在备份数据库..." docker exec aiagent-mysql mysqldump -u root -p"${MYSQL_ROOT_PASSWORD:-change-me}" \ agent_db 2>/dev/null > "$BACKUP_DIR/agent_db.sql" || \ warn "数据库备份失败(可以手动重试)" [ -s "$BACKUP_DIR/agent_db.sql" ] && info "数据库已备份到 $BACKUP_DIR/agent_db.sql" fi # ─── 2. 拉取更新 ───────────────────────────────────────────────────────────── echo "" info "正在拉取最新镜像并重新构建..." $COMPOSE -f "$COMPOSE_FILE" pull 2>/dev/null || true $COMPOSE -f "$COMPOSE_FILE" build --pull # ─── 3. 滚动重启 ───────────────────────────────────────────────────────────── echo "" info "正在重启服务(零停机)..." # 按依赖顺序重启:先数据库,再后端,最后前端 $COMPOSE -f "$COMPOSE_FILE" up -d mysql redis sleep 5 $COMPOSE -f "$COMPOSE_FILE" up -d backend celery-worker celery-beat sleep 5 $COMPOSE -f "$COMPOSE_FILE" up -d frontend # ─── 4. 清理旧镜像 ─────────────────────────────────────────────────────────── echo "" info "正在清理旧镜像..." docker image prune -f 2>/dev/null || true # ─── 5. 验证 ───────────────────────────────────────────────────────────────── echo "" info "等待服务就绪..." for i in $(seq 1 30); do if curl -sf http://localhost:8037/docs >/dev/null 2>&1; then info "后端服务正常" break fi sleep 2 done echo "" echo -e "${CYAN}── 当前服务状态 ──${NC}" $COMPOSE -f "$COMPOSE_FILE" ps echo "" echo -e "${GREEN}升级完成!${NC}" echo "" echo "版本: $(date +%Y-%m-%d_%H:%M:%S)" echo "备份目录: $BACKUP_DIR" echo "回滚方式: docker compose -f docker-compose.prod.yml down && docker compose -f docker-compose.prod.yml up -d" echo ""