本文目录导读:

Shell脚本实现重试退避策略有多种方式,以下是几种常见实现:
指数退避(Exponential Backoff)
#!/bin/bash
function retry_command() {
local max_attempts=${1:-5}
local initial_delay=${2:-1}
local backoff_factor=${3:-2}
local max_delay=${4:-60}
local attempt=1
local delay=$initial_delay
while [ $attempt -le $max_attempts ]; do
echo "尝试 $attempt/$max_attempts..."
if "$@${@:5}" 2>/dev/null; then
echo "成功执行"
return 0
fi
echo "失败,等待 ${delay}秒后重试..."
sleep $delay
# 计算下一次延迟
delay=$((delay * backoff_factor))
if [ $delay -gt $max_delay ]; then
delay=$max_delay
fi
((attempt++))
done
echo "所有重试都失败"
return 1
}
# 使用示例
retry_command 5 1 2 30 "your_command_here"
带随机抖动的指数退避
#!/bin/bash
function retry_with_jitter() {
local max_attempts=${1:-5}
local base_delay=${2:-2}
local backoff_factor=${3:-2}
local max_delay=${4:-120}
local attempt=1
local delay=$base_delay
while [ $attempt -le $max_attempts ]; do
echo "尝试 $attempt/$max_attempts..."
# 执行命令
if eval "${@:5}"; then
echo "成功执行"
return 0
fi
echo "失败,等待 ${delay}秒后重试..."
# 添加随机抖动
local jitter=$((RANDOM % 5 + 1))
sleep $((delay + jitter))
# 计算下一次延迟
delay=$((delay * backoff_factor))
if [ $delay -gt $max_delay ]; then
delay=$max_delay
fi
((attempt++))
done
echo "所有重试都失败"
return 1
}
固定间隔重试
#!/bin/bash
function retry_fixed_interval() {
local max_attempts=${1:-3}
local interval=${2:-5}
local attempt=1
while [ $attempt -le $max_attempts ]; do
echo "尝试 $attempt/$max_attempts..."
if "$@${@:3}"; then
echo "成功"
return 0
fi
if [ $attempt -lt $max_attempts ]; then
echo "失败,${interval}秒后重试..."
sleep $interval
fi
((attempt++))
done
echo "所有重试失败"
return 1
}
高级版本:支持错误处理和日志
#!/bin/bash
function advanced_retry() {
# 配置参数
local max_attempts=5
local initial_delay=1
local max_delay=60
local backoff_factor=2
local retryable_exit_codes=(1 2 3) # 可重试的错误码
local attempt=1
local delay=$initial_delay
local logfile="/var/log/retry.log"
while [ $attempt -le $max_attempts ]; do
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 尝试 $attempt/$max_attempts" | tee -a $logfile
# 执行命令并捕获输出和退出码
output=$("$@" 2>&1)
exit_code=$?
if [ $exit_code -eq 0 ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 成功执行" | tee -a $logfile
return 0
fi
# 检查退出码是否可重试
local retryable=false
for code in "${retryable_exit_codes[@]}"; do
if [ $exit_code -eq $code ]; then
retryable=true
break
fi
done
if [ "$retryable" = false ] && [ $attempt -lt $max_attempts ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 不可重试的错误码: $exit_code" | tee -a $logfile
return $exit_code
fi
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 失败 (退出码: $exit_code)" | tee -a $logfile
if [ $attempt -lt $max_attempts ]; then
echo "等待 ${delay}秒后重试..." | tee -a $logfile
sleep $delay
# 指数退避
delay=$((delay * backoff_factor))
[ $delay -gt $max_delay ] && delay=$max_delay
fi
((attempt++))
done
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 所有重试都失败" | tee -a $logfile
return 1
}
使用 curl 的重试示例
#!/bin/bash
# curl 内置的重试功能
function curl_with_retry() {
local url=$1
local max_retries=${2:-3}
curl \
--retry $max_retries \
--retry-delay 5 \
--retry-max-time 60 \
--retry-connrefused \
-s \
-o /dev/null \
-w "%{http_code}" \
"$url"
}
# 使用示例
curl_with_retry "https://api.example.com" 5
实际使用示例
#!/bin/bash
source ./retry_functions.sh
# 示例1: 重试文件下载
retry_with_jitter 5 2 2 30 "wget -q https://example.com/largefile.zip"
# 示例2: 重试数据库连接
retry_command 3 5 1 30 "mysql -h host -u user -ppassword -e 'SELECT 1'"
# 示例3: 重试 API 调用
advanced_retry "curl -X POST https://api.example.com/data"
# 示例4: 重试直到成功或超时
TIMEOUT=300
START_TIME=$(date +%s)
while true; do
if your_command; then
break
fi
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - START_TIME))
if [ $ELAPSED -ge $TIMEOUT ]; then
echo "超时"
exit 1
fi
sleep 5
done
推荐的退避策略
- 指数退避:适用于瞬时故障
- 指数退避+随机抖动:避免惊群效应
- 固定间隔:简单可预测,适用于非临界操作
- 线性递增:适用于需要逐渐增加间隔的场景
选择哪种策略取决于你的具体需求和失败原因。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播