#!/bin/bash ############################################################################### # 服务器端回滚脚本 # 此脚本在服务器上执行,由本地回滚脚本远程调用 ############################################################################### set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' ############################################################################### # 配置变量(通过环境变量传入) ############################################################################### PRODUCTION_PATH="${PRODUCTION_PATH:-/var/www/valuefrontier.cn}" BACKUP_DIR="${BACKUP_DIR:-/home/ubuntu/deployments}" ############################################################################### # 函数:打印带颜色的消息 ############################################################################### log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } ############################################################################### # 函数:列出可用的备份版本 ############################################################################### list_backups() { log_info "可用的备份版本:" echo "" if [ ! -d "$BACKUP_DIR" ]; then log_error "备份目录不存在: $BACKUP_DIR" return 1 fi cd "$BACKUP_DIR" # 获取所有备份目录,按时间倒序 local backups=($(find . -maxdepth 1 -type d -name "backup-*" | sort -r)) if [ ${#backups[@]} -eq 0 ]; then log_warning "没有可用的备份版本" return 1 fi local index=1 for backup in "${backups[@]}"; do local backup_name=$(basename "$backup") local backup_time=$(echo "$backup_name" | sed 's/backup-//' | sed 's/-/ /') local is_current="" # 检查是否是当前版本 if [ -L "$BACKUP_DIR/current" ]; then local current_link=$(readlink "$BACKUP_DIR/current") if [ "$current_link" = "$backup" ] || [ "$current_link" = "$BACKUP_DIR/$backup_name" ]; then is_current=" ${GREEN}[当前版本]${NC}" fi fi echo -e " $index. $backup_name ($backup_time)$is_current" ((index++)) done echo "" return 0 } ############################################################################### # 函数:回滚到指定版本 ############################################################################### rollback_to_version() { local version_index="${1:-1}" log_info "开始回滚到版本 #$version_index..." if [ ! -d "$BACKUP_DIR" ]; then log_error "备份目录不存在: $BACKUP_DIR" exit 1 fi cd "$BACKUP_DIR" # 获取所有备份目录,按时间倒序 local backups=($(find . -maxdepth 1 -type d -name "backup-*" | sort -r)) if [ ${#backups[@]} -eq 0 ]; then log_error "没有可用的备份版本" exit 1 fi # 检查索引是否有效 if [ "$version_index" -lt 1 ] || [ "$version_index" -gt "${#backups[@]}" ]; then log_error "无效的版本索引: $version_index (可用范围: 1-${#backups[@]})" exit 1 fi # 获取目标备份 local target_index=$((version_index - 1)) local target_backup="${backups[$target_index]}" local backup_name=$(basename "$target_backup") log_info "目标版本: $backup_name" # 检查备份是否存在 if [ ! -d "$target_backup" ]; then log_error "备份版本不存在: $target_backup" exit 1 fi # 清空生产目录 log_info "清空生产目录: $PRODUCTION_PATH" rm -rf "$PRODUCTION_PATH"/* # 恢复备份 log_info "恢复备份文件..." cp -r "$target_backup"/* "$PRODUCTION_PATH/" || { log_error "恢复备份失败" exit 1 } # 设置权限 chmod -R 755 "$PRODUCTION_PATH" # 更新 current 符号链接 ln -snf "$target_backup" "$BACKUP_DIR/current" log_success "回滚完成" echo "" echo "========================================" echo " 回滚成功!" echo "========================================" echo "目标版本: $backup_name" echo "" # 输出结果供本地脚本解析 echo "ROLLBACK_SUCCESS=true" echo "ROLLBACK_VERSION=$backup_name" } ############################################################################### # 主函数 ############################################################################### main() { local action="${1:-list}" echo "" echo "========================================" echo " 服务器端回滚脚本" echo "========================================" echo "" case "$action" in list) list_backups ;; rollback) local version_index="${2:-1}" rollback_to_version "$version_index" ;; *) log_error "未知操作: $action" echo "用法: $0 {list|rollback} [version_index]" exit 1 ;; esac } # 执行主函数 main "$@"