本文目录导读:

在Shell脚本中实现并行发布策略,主要有以下几种常用方法:
使用 & 后台运行 + wait 等待
最简单的并行执行方式:
#!/bin/bash
# 并行发布函数
deploy_service() {
local service=$1
local version=$2
echo "[$(date +%H:%M:%S)] 开始发布 $service (版本: $version)"
sleep $((RANDOM % 5 + 2)) # 模拟发布过程
echo "[$(date +%H:%M:%S)] $service 发布完成"
return $((RANDOM % 2))
}
# 定义要发布的服务列表
services=("service-a" "service-b" "service-c" "service-d")
version="v2.1.0"
# 并行发布所有服务
echo "开始并行发布..."
for svc in "${services[@]}"; do
deploy_service "$svc" "$version" &
pids+=($!) # 保存后台进程PID
done
# 等待所有发布完成
failed=0
for i in "${!pids[@]}"; do
wait "${pids[$i]}"
if [ $? -ne 0 ]; then
echo "${services[$i]} 发布失败"
((failed++))
fi
done
# 输出结果汇总
echo "===== 发布结果 ====="
echo "总共: ${#services[@]} 个服务"
echo "成功: $(( ${#services[@]} - failed )) 个"
echo "失败: $failed 个"
[ $failed -eq 0 ] && exit 0 || exit 1
控制并发数量(信号量机制)
当服务很多时,需要限制并行数量:
#!/bin/bash
# 使用文件描述符控制并发数
concurrent_deploy() {
local max_jobs=$1 # 最大并行数
local services=("${!2}") # 服务列表
local version=$3
# 创建命名管道用于控制并发
tmpdir=$(mktemp -d)
mkfifo "$tmpdir/fifo"
exec 3<>"$tmpdir/fifo"
# 初始化信号量
for ((i=0; i<max_jobs; i++)); do
echo >&3
done
# 并行发布
for svc in "${services[@]}"; do
read -u 3 # 获取信号量
{
echo "[$(date +%H:%M:%S)] 开始发布 $svc"
sleep $((RANDOM % 3 + 1))
echo "[$(date +%H:%M:%S)] $svc 完成"
echo >&3 # 释放信号量
} &
done
# 等待所有完成
wait
exec 3>&-
rm -rf "$tmpdir"
}
# 使用示例
services=("svc-1" "svc-2" "svc-3" "svc-4" "svc-5")
concurrent_deploy 3 services[@] "v2.0.0"
使用 GNU Parallel 工具
更专业的并行处理工具:
#!/bin/bash
# 安装: apt-get install parallel 或 brew install parallel
deploy_one_service() {
local service=$1
local version=$2
echo "开始发布 $service"
# 模拟发布步骤
echo " 1. 拉取镜像: $service:$version"
sleep 1
echo " 2. 停止旧版本"
sleep 1
echo " 3. 启动新版本"
sleep 1
echo " 4. 健康检查"
sleep 1
echo "$service 发布完成"
}
export -f deploy_one_service # 导出函数供parallel使用
# 定义服务列表
SERVICES="service-a service-b service-c service-d"
VERSION="v3.0.0"
# 并行执行,控制并发数
echo "使用GNU Parallel并行发布..."
echo "$SERVICES" | tr ' ' '\n' | parallel -j 4 deploy_one_service {} $VERSION
# 带进度显示
echo "$SERVICES" | tr ' ' '\n' | parallel --progress -j 3 deploy_one_service {} $VERSION
带错误处理和回滚策略
更完整的生产环境发布脚本:
#!/bin/bash
# 配置
MAX_PARALLEL=3
VERSION=${1:-"latest"}
DEPLOY_LOG="/var/log/deploy_$(date +%Y%m%d_%H%M%S).log"
# 服务配置
declare -A SERVICES
SERVICES=(
["api-gateway"]="8080"
["user-service"]="8081"
["order-service"]="8082"
["payment-service"]="8083"
["notification-service"]="8084"
)
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$DEPLOY_LOG"
}
# 健康检查
health_check() {
local service=$1
local port=$2
local retries=10
for ((i=1; i<=retries; i++)); do
if curl -sf "http://localhost:$port/health" > /dev/null 2>&1; then
return 0
fi
sleep 2
done
return 1
}
# 发布单个服务
deploy_service() {
local service=$1
local port=$2
local version=$3
local result_file=$4
log "[$service] 开始部署..."
# 模拟部署步骤
{
log "[$service] 拉取镜像: $service:$version"
sleep 2
# 模拟失败(10%概率)
if [ $((RANDOM % 10)) -eq 0 ]; then
log "[$service] ❌ 部署失败"
echo "$service:FAILED" >> "$result_file"
return 1
}
log "[$service] 启动新版本..."
sleep 3
# 健康检查
if health_check "$service" "$port"; then
log "[$service] ✅ 部署成功"
echo "$service:SUCCESS" >> "$result_file"
return 0
else
log "[$service] ❌ 健康检查失败,触发回滚"
# 执行回滚操作
echo "$service:ROLLBACK" >> "$result_file"
return 1
fi
}
}
# 主函数
main() {
local result_file=$(mktemp)
local pids=()
log "开始并行发布,版本: $VERSION"
log "最大并行数: $MAX_PARALLEL"
# 使用队列控制并发数
local queue=()
local running=0
for service in "${!SERVICES[@]}"; do
port=${SERVICES[$service]}
# 等待,直到当前并行数小于最大限制
while [ $running -ge $MAX_PARALLEL ]; do
for pid in "${pids[@]}"; do
if ! kill -0 $pid 2>/dev/null; then
wait $pid
((running--))
fi
done
sleep 1
done
# 启动新的部署进程
deploy_service "$service" "$port" "$VERSION" "$result_file" &
pids+=($!)
((running++))
done
# 等待所有进程完成
wait
# 汇总结果
log "===== 发布汇总 ====="
local success=0
local failed=0
local rollback=0
while IFS= read -r line; do
service=${line%:*}
status=${line#*:}
case $status in
SUCCESS) ((success++)) ;;
FAILED) ((failed++)) ;;
ROLLBACK) ((rollback++)) ;;
esac
log " $service: $status"
done < "$result_file"
rm -f "$result_file"
log "统计: 成功=$success, 失败=$failed, 回滚=$rollback"
if [ $failed -eq 0 ] && [ $rollback -eq 0 ]; then
log "✅ 所有服务发布成功"
return 0
else
log "⚠️ 部分服务发布异常"
return 1
fi
}
# 执行
main "$@"
使用 xargs 实现并行
简单快速的并行方案:
#!/bin/bash
# 并行发布函数
deploy() {
local service=$1
echo "发布 $service..."
sleep $((RANDOM % 3 + 1))
echo "$service 完成"
}
export -f deploy
# 服务列表
cat << EOF > services.txt
service-a
service-b
service-c
service-d
service-e
EOF
# 并行执行,-P 控制并行数
cat services.txt | xargs -I {} -P 3 bash -c 'deploy "$@"' _ {}
最佳实践建议
- 错误处理:每个并行任务都要捕获错误并进行处理
- 日志记录:集中收集所有并行任务的日志
- 资源限制:根据服务器资源合理设置并发数
- 超时控制:为每个任务设置超时时间
- 回滚机制:单个任务失败时,最好有自动回滚能力
# 超时控制示例
deploy_with_timeout() {
local timeout=$1
shift
timeout $timeout "$@" &
pid=$!
wait $pid 2>/dev/null
return $?
}
# 使用
deploy_with_timeout 300 deploy_service "svc-a" "v1.0.0"
选择哪种方式取决于你的具体需求:
- 简单场景:使用
&+wait - 需要控制并发:使用管道信号量或 GNU Parallel
- 生产环境:使用完整的错误处理和回滚方案
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播