Shell脚本如何实现全自动发布策略

wen 实用脚本 25

本文目录导读:

Shell脚本如何实现全自动发布策略

  1. 基础发布脚本框架
  2. 蓝绿部署策略
  3. 滚动更新策略
  4. 金丝雀发布策略
  5. 完整发布流程
  6. 辅助函数
  7. 使用示例

我来详细介绍Shell脚本实现全自动发布策略的几种方式:

基础发布脚本框架

#!/bin/bash
# 配置变量
PROJECT_NAME="my-app"
GIT_REPO="git@github.com:user/repo.git"
BRANCH="main"
DEPLOY_DIR="/var/www/$PROJECT_NAME"
BACKUP_DIR="/var/backups/$PROJECT_NAME"
LOG_FILE="/var/log/deploy/$PROJECT_NAME-deploy.log"
# 颜色输出
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 日志函数
log() {
    echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}
# 健康检查
health_check() {
    local max_retries=30
    local retry_count=0
    local url="http://localhost:8080/health"
    while [ $retry_count -lt $max_retries ]; do
        if curl -f -s $url > /dev/null 2>&1; then
            log "${GREEN}Health check passed${NC}"
            return 0
        fi
        sleep 1
        ((retry_count++))
    done
    log "${RED}Health check failed after $max_retries retries${NC}"
    return 1
}

蓝绿部署策略

#!/bin/bash
BLUE_DIR="/var/www/app-blue"
GREEN_DIR="/var/www/app-green"
ACTIVE_SYMLINK="/var/www/app"
NGINX_CONFIG="/etc/nginx/sites-enabled/app"
blue_green_deploy() {
    # 确定当前活跃环境
    if [ -L "$ACTIVE_SYMLINK" ] && [ "$(readlink $ACTIVE_SYMLINK)" == "$BLUE_DIR" ]; then
        INACTIVE="$GREEN_DIR"
        ACTIVE="$BLUE_DIR"
        NEW_ENV="green"
    else
        INACTIVE="$GREEN_DIR"
        ACTIVE="$BLUE_DIR"
        NEW_ENV="blue"
    fi
    log "Deploying to $NEW_ENV environment"
    # 部署到非活跃环境
    rsync -av --delete --exclude='.env' "$BUILD_DIR/" "$INACTIVE/"
    # 更新配置
    cp "$ACTIVE/.env" "$INACTIVE/"
    # 执行数据库迁移
    cd $INACTIVE && ./artisan migrate --force
    # 切换流量
    ln -sfn "$INACTIVE" "$ACTIVE_SYMLINK"
    # 重启服务
    sudo systemctl reload nginx
    # 健康检查
    if health_check; then
        log "${GREEN}Blue-Green deploy to $NEW_ENV successful${NC}"
    else
        # 回滚
        ln -sfn "$ACTIVE" "$ACTIVE_SYMLINK"
        sudo systemctl reload nginx
        log "${RED}Deploy failed, rolled back to $ACTIVE${NC}"
        return 1
    fi
}

滚动更新策略

#!/bin/bash
SERVICE_NAME="my-service"
INSTANCES=("instance-1" "instance-2" "instance-3")
BATCH_SIZE=1
HEALTH_CHECK_URL="http://localhost:8080/health"
rolling_update() {
    local total=${#INSTANCES[@]}
    local batch=0
    for ((i=0; i<$total; i+=BATCH_SIZE)); do
        batch=$((batch + 1))
        log "Starting batch $batch of $(( (total + BATCH_SIZE - 1) / BATCH_SIZE ))"
        # 获取当前批次实例
        local batch_instances=("${INSTANCES[@]:i:BATCH_SIZE}")
        # 停止当前批次实例
        for instance in "${batch_instances[@]}"; do
            log "Draining connections for $instance"
            docker stop $instance
            docker rm $instance
        done
        # 启动新版本实例
        for instance in "${batch_instances[@]}"; do
            log "Starting new version of $instance"
            docker run -d --name $instance $NEW_IMAGE
            # 等待实例就绪
            sleep 10
            # 健康检查
            if ! health_check; then
                log "${RED}Health check failed for $instance, rolling back batch${NC}"
                return 1
            fi
        done
        # 批次间等待
        if [ $((i + BATCH_SIZE)) -lt $total ]; then
            log "Waiting 30 seconds before next batch..."
            sleep 30
        fi
    done
    log "${GREEN}Rolling update completed successfully${NC}"
}

金丝雀发布策略

#!/bin/bash
CANARY_PERCENTAGE=20
CANARY_INSTANCES=1
PRODUCTION_INSTANCES=4
canary_deploy() {
    local canary_count=$CANARY_INSTANCES
    local production_count=$PRODUCTION_INSTANCES
    log "Starting canary deployment (${CANARY_PERCENTAGE}% traffic)"
    # 部署金丝雀实例
    log "Deploying $canary_count canary instances"
    docker-compose scale app_canary=$canary_count
    # 等待金丝雀稳定
    sleep 60
    # 监控金丝雀
    local error_rate=$(check_canary_errors)
    if [ $(echo "$error_rate > 0.01" | bc) -eq 1 ]; then
        log "${RED}Canary error rate too high: ${error_rate}%, rolling back${NC}"
        docker-compose scale app_canary=0
        return 1
    fi
    # 逐步增加流量
    for percentage in 50 80 100; do
        log "Increasing traffic to ${percentage}%"
        adjust_traffic $percentage
        sleep 120
        if ! check_deployment_health; then
            log "${RED}Deployment health check failed at ${percentage}%${NC}"
            rollback_canary
            return 1
        fi
    done
    # 替换生产环境
    log "Replacing production instances with new version"
    docker-compose up -d --scale app=$production_count app
    docker-compose scale app_canary=0
    log "${GREEN}Canary deployment completed successfully${NC}"
}

完整发布流程

#!/bin/bash
# 主发布函数
auto_deploy() {
    local version=$1
    local strategy=${2:-"blue-green"}  # 默认蓝绿部署
    log "=========================================="
    log "Starting auto deploy v${version}"
    log "Strategy: $strategy"
    log "=========================================="
    # 1. 前置检查
    log "Phase 1: Pre-deployment checks"
    if ! pre_deploy_checks; then
        log "${RED}Pre-deployment checks failed${NC}"
        notify_failure "Pre-deployment checks failed"
        return 1
    fi
    # 2. 代码获取
    log "Phase 2: Fetching code"
    if ! fetch_code $version; then
        log "${RED}Code fetch failed${NC}"
        notify_failure "Code fetch failed"
        return 1
    fi
    # 3. 构建
    log "Phase 3: Building application"
    if ! build_application; then
        log "${RED}Build failed${NC}"
        notify_failure "Build failed"
        return 1
    fi
    # 4. 运行测试
    log "Phase 4: Running tests"
    if ! run_tests; then
        log "${RED}Tests failed${NC}"
        notify_failure "Tests failed"
        return 1
    fi
    # 5. 部署
    log "Phase 5: Deploying"
    case $strategy in
        "blue-green")
            blue_green_deploy
            ;;
        "rolling")
            rolling_update
            ;;
        "canary")
            canary_deploy
            ;;
        *)
            log "${RED}Unknown strategy: $strategy${NC}"
            return 1
            ;;
    esac
    if [ $? -ne 0 ]; then
        log "${RED}Deploy failed${NC}"
        notify_failure "Deploy failed"
        return 1
    fi
    # 6. 部署后检查
    log "Phase 6: Post-deployment checks"
    if ! post_deploy_checks; then
        log "${RED}Post-deployment checks failed, rolling back${NC}"
        rollback
        return 1
    fi
    # 7. 通知成功
    log "${GREEN}Deploy v${version} completed successfully${NC}"
    notify_success "Deploy v${version} completed"
    # 清理旧版本
    cleanup_old_versions
}
# 执行入口
if [ $# -lt 1 ]; then
    echo "Usage: $0 <version> [strategy]"
    exit 1
fi
auto_deploy "$@"

辅助函数

#!/bin/bash
# 通知函数(支持多种通知方式)
notify() {
    local level=$1
    local message=$2
    # Slack通知
    if [ -n "$SLACK_WEBHOOK_URL" ]; then
        curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"[$level] $message\"}" \
            $SLACK_WEBHOOK_URL
    fi
    # 邮件通知
    if [ -n "$EMAIL_RECIPIENT" ]; then
        echo "$message" | mail -s "[$level] Deploy Notification" $EMAIL_RECIPIENT
    fi
    # 钉钉/企业微信通知
    if [ -n "$DINGTALK_WEBHOOK" ]; then
        curl -X POST -H 'Content-Type: application/json' \
            --data "{\"msgtype\":\"text\",\"text\":{\"content\":\"$message\"}}" \
            $DINGTALK_WEBHOOK
    fi
}
# 并发执行
parallel_exec() {
    local max_parallel=$1
    shift
    local commands=("$@")
    for cmd in "${commands[@]}"; do
        eval "$cmd" &
        if [ $(jobs -r | wc -l) -ge $max_parallel ]; then
            wait -n
        fi
    done
    wait
}
# 超时执行
timeout_exec() {
    local timeout=$1
    local command=$2
    (
        eval "$command" &
        child=$!
        trap '' SIGTERM
        (sleep $timeout; kill $child 2>/dev/null) &
        wait $child
    )
}
# 锁机制防止并发部署
acquire_lock() {
    local lock_file="/var/lock/deploy.lock"
    if ! mkdir $lock_file 2>/dev/null; then
        log "${YELLOW}Another deploy is in progress${NC}"
        exit 1
    fi
    trap 'rm -rf $lock_file' EXIT
}
# 清理函数
cleanup_old_versions() {
    log "Cleaning up old versions..."
    # 保留最近5个版本
    ls -t $DEPLOY_DIR/versions/ | tail -n +6 | while read version; do
        rm -rf "$DEPLOY_DIR/versions/$version"
        log "Removed old version: $version"
    done
}

使用示例

# 基本使用
./deploy.sh v1.2.3
# 指定策略
./deploy.sh v1.2.3 rolling
# 金丝雀发布
./deploy.sh v1.2.3 canary
# 带参数
CANARY_PERCENTAGE=10 ./deploy.sh v1.2.3 canary

这个脚本框架实现了多种发布策略,具备以下特点:

  • 可视化日志
  • 自动健康检查
  • 自动回滚机制
  • 多策略支持
  • 通知集成
  • 并发控制
  • 锁机制防冲突

使用时请根据实际需求调整配置和逻辑。

抱歉,评论功能暂时关闭!