本文目录导读:

使用Shell脚本实现自动化回滚策略,主要涉及备份机制、版本管理和回滚触发条件,下面提供一个完整的实现方案。
基础回滚脚本框架
#!/bin/bash
# 配置变量
APP_NAME="myapp"
DEPLOY_DIR="/var/www/$APP_NAME"
BACKUP_DIR="/backups/$APP_NAME"
CURRENT_LINK="$DEPLOY_DIR/current"
ROLLBACK_POINTS=5 # 保留最近5个回滚点
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
# 创建备份
create_backup() {
local version=$1
local backup_path="$BACKUP_DIR/$version"
log "创建备份: $version"
# 创建备份目录
mkdir -p "$backup_path"
# 备份当前部署(排除日志和缓存)
rsync -a --exclude='logs/' --exclude='cache/' \
"$CURRENT_LINK/" "$backup_path/"
# 备份数据库(如果需要)
if [ -f "$DEPLOY_DIR/db_config.sh" ]; then
source "$DEPLOY_DIR/db_config.sh"
mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > \
"$backup_path/database.sql"
fi
# 记录备份元数据
cat > "$backup_path/backup_meta.txt" << EOF
Backup Time: $(date '+%Y-%m-%d %H:%M:%S')
Version: $version
Previous Version: $(readlink -f "$CURRENT_LINK" 2>/dev/null || echo "initial")
EOF
# 清理旧备份
clean_old_backups
}
# 执行回滚
rollback() {
local target_version=$1
if [ ! -d "$BACKUP_DIR/$target_version" ]; then
error "回滚版本 $target_version 不存在"
fi
log "开始回滚到版本: $target_version"
# 停止服务
systemctl stop "$APP_NAME"
# 备份当前版本(以防需要再次回滚)
current_version=$(get_current_version)
create_backup "pre_rollback_$(date '+%Y%m%d_%H%M%S')"
# 执行回滚
rm -rf "$CURRENT_LINK"
ln -sf "$BACKUP_DIR/$target_version" "$CURRENT_LINK"
# 恢复数据库(如果需要)
if [ -f "$BACKUP_DIR/$target_version/database.sql" ]; then
log "恢复数据库..."
source "$DEPLOY_DIR/db_config.sh"
mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" < \
"$BACKUP_DIR/$target_version/database.sql"
fi
# 执行回调钩子
if [ -f "$DEPLOY_DIR/rollback_hooks.sh" ]; then
source "$DEPLOY_DIR/rollback_hooks.sh"
post_rollback "$target_version" "$current_version"
fi
# 启动服务
systemctl start "$APP_NAME"
# 健康检查
if health_check; then
log "回滚成功!当前版本: $target_version"
else
error "回滚后健康检查失败,请手动排查"
fi
}
# 健康检查
health_check() {
local max_attempts=30
local attempt=0
while [ $attempt -lt $max_attempts ]; do
if curl -s -f "http://localhost/health" > /dev/null 2>&1; then
return 0
fi
attempt=$((attempt + 1))
sleep 1
done
return 1
}
# 清理旧备份
clean_old_backups() {
local backup_list=$(ls -1t "$BACKUP_DIR")
local count=0
for backup in $backup_list; do
count=$((count + 1))
if [ $count -gt $ROLLBACK_POINTS ]; then
rm -rf "$BACKUP_DIR/$backup"
log "删除旧备份: $backup"
fi
done
}
# 获取当前版本
get_current_version() {
readlink -f "$CURRENT_LINK" | awk -F'/' '{print $NF}'
}
# 显示版本列表
list_versions() {
echo -e "${YELLOW}可用回滚版本:${NC}"
ls -1t "$BACKUP_DIR" 2>/dev/null || echo "无可用备份"
}
# 自动回滚(部署失败时触发)
auto_rollback() {
local deploy_version=$1
log "自动回滚部署版本: $deploy_version"
# 查找部署前的版本
local previous_version=$(cat "$BACKUP_DIR/$deploy_version/backup_meta.txt" | \
grep "Previous Version" | awk -F': ' '{print $2}')
if [ -n "$previous_version" ] && [ -d "$BACKUP_DIR/$previous_version" ]; then
rollback "$previous_version"
else
# 如果没有找到前一个版本,使用最后一个稳定版本
local last_stable=$(ls -1t "$BACKUP_DIR" | head -2 | tail -1)
if [ -n "$last_stable" ]; then
rollback "$last_stable"
else
error "无法找到可回滚的版本"
fi
fi
}
# 主函数
main() {
case "$1" in
create)
create_backup "$2"
;;
rollback)
rollback "$2"
;;
auto)
auto_rollback "$2"
;;
list)
list_versions
;;
*)
echo "用法: $0 {create|rollback|auto|list} [version]"
exit 1
;;
esac
}
main "$@"
集成部署脚本
#!/bin/bash
# deploy_with_rollback.sh - 带自动回滚的部署脚本
source "$(dirname "$0")/rollback.sh"
DEPLOY_VERSION="v$(date '+%Y%m%d_%H%M%S')"
SOURCE_DIR="/tmp/$APP_NAME-$DEPLOY_VERSION"
deploy() {
log "开始部署版本: $DEPLOY_VERSION"
# 1. 创建新版本目录
mkdir -p "$SOURCE_DIR"
# 2. 拉取代码(示例)
git clone -b main "$REPO_URL" "$SOURCE_DIR" 2>/dev/null || error "git clone 失败"
# 3. 安装依赖
cd "$SOURCE_DIR"
npm install 2>/dev/null || { auto_rollback "$DEPLOY_VERSION"; exit 1; }
npm run build 2>/dev/null || { auto_rollback "$DEPLOY_VERSION"; exit 1; }
# 4. 备份当前版本
create_backup "$DEPLOY_VERSION"
# 5. 切换版本
rm -f "$CURRENT_LINK"
ln -sf "$SOURCE_DIR" "$CURRENT_LINK"
# 6. 重启服务
systemctl restart "$APP_NAME"
# 7. 健康检查
if ! health_check; then
log "部署后健康检查失败,触发自动回滚"
auto_rollback "$DEPLOY_VERSION"
exit 1
fi
log "部署成功! 版本: $DEPLOY_VERSION"
}
deploy
配置文件和钩子函数
# rollback_config.sh - 配置文件 # 应用配置 APP_NAME="myapp" DEPLOY_DIR="/var/www/$APP_NAME" BACKUP_DIR="/backups/$APP_NAME" REPO_URL="https://github.com/user/repo.git" # 保留最近的回滚点数量 ROLLBACK_POINTS=5 # 健康检查配置 HEALTH_CHECK_URL="http://localhost/health" HEALTH_CHECK_TIMEOUT=30 HEALTH_CHECK_RETRY_INTERVAL=2 # 数据库配置 DB_HOST="localhost" DB_NAME="myapp_db" DB_USER="db_user" DB_PASS="db_password" # 通知配置 ENABLE_NOTIFICATIONS=true NOTIFICATION_EMAIL="admin@example.com" SLACK_WEBHOOK_URL="https://hooks.slack.com/services/xxx"
# rollback_hooks.sh - 回滚钩子函数
post_rollback() {
local target_version=$1
local previous_version=$2
log "执行回滚后钩子函数"
# 清理缓存
if [ -d "$CURRENT_LINK/var/cache" ]; then
rm -rf "$CURRENT_LINK/var/cache/*"
log "清理应用缓存"
fi
# 重启队列服务
if systemctl list-units --type=service | grep -q "$APP_NAME-worker"; then
systemctl restart "$APP_NAME-worker"
log "重启队列服务"
fi
# 发送通知
if [ "$ENABLE_NOTIFICATIONS" = true ]; then
send_notification "回滚完成" "版本从 $previous_version 回滚到 $target_version"
fi
}
send_notification() {
local subject=$1
local message=$2
# 邮件通知
echo "$message" | mail -s "[$APP_NAME] $subject" "$NOTIFICATION_EMAIL"
# Slack通知
if [ -n "$SLACK_WEBHOOK_URL" ]; then
curl -s -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"[$APP_NAME] $subject: $message\"}" \
"$SLACK_WEBHOOK_URL" > /dev/null 2>&1
fi
}
使用示例
# 1. 创建备份 ./rollback.sh create "v20240301" # 2. 手动回滚到指定版本 ./rollback.sh rollback "v20240301" # 3. 查看可用版本 ./rollback.sh list # 4. 自动化部署(含自动回滚) ./deploy_with_rollback.sh # 5. 自动回滚到上一个版本 ./rollback.sh auto "v20240301"
高级特性
灰度发布支持
# canary_deploy.sh - 金丝雀发布
CANARY_RATIO=10 # 10%的流量
canary_deploy() {
local new_version=$1
# 部署到金丝雀服务器
create_backup "$new_version"
# 配置负载均衡器将10%流量导向新版本
configure_load_balancer "canary" $CANARY_RATIO
# 监控一段时间
sleep 300
# 如果监控无异常,全量发布
if ! check_canary_metrics; then
auto_rollback "$new_version"
return 1
fi
# 全量发布
rollback_to_canary "$new_version"
}
数据库版本管理
# db_migration.sh - 数据库迁移管理
rollback_database() {
local target_version=$1
local migration_dir="$BACKUP_DIR/$target_version/migrations"
if [ -d "$migration_dir" ]; then
# 按时间逆序执行回滚脚本
for migration in $(ls -1r "$migration_dir"/*.sql); do
log "执行数据库回滚: $(basename $migration)"
mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$migration"
done
fi
}
这个方案提供了完整的回滚功能,包括备份管理、自动回滚、健康检查、通知告警等特性,可以根据具体需求进行定制和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播