本文目录导读:

我来详细介绍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
这个脚本框架实现了多种发布策略,具备以下特点:
- 可视化日志
- 自动健康检查
- 自动回滚机制
- 多策略支持
- 通知集成
- 并发控制
- 锁机制防冲突
使用时请根据实际需求调整配置和逻辑。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播