← 中文资源

简体中文版本

指数退避重试

以指数退避与有界次数重试 shell 命令,次数耗尽时明确失败。

阅读英文原文

功能说明

该示例提供一个可复用的重试函数:接收最大尝试次数与要执行的命令,命令失败时按 1 秒、2 秒、4 秒、8 秒的节奏等待后重试,直到成功或次数耗尽。失败时向标准错误输出诊断信息并以非零码返回,使调用方与管道能感知失败。

关键代码

函数用 shift 把首个参数取出后,把剩余参数当作命令整体执行,从而保留参数中的空格与引号。“$@”加引号是正确传递带空格参数的关键。until 循环在命令成功时结束;每次失败递增尝试计数并在达到上限时返回 1。延迟每轮翻倍实现指数退避。set -euo pipefail 让脚本更早暴露错误。

使用注意

该函数只按固定指数退避,未加抖动,多实例同时重试可能同步成惊群,生产脚本应加入随机抖动。重试只应针对可恢复的失败,命令若因输入错误而失败,重试只是浪费时间,可结合 curl 的 –fail 与退出码判断。务必保留每次调用的日志以便排查。重试命令必须幂等,写入型操作需要幂等键,否则一次超时可能变成两次副作用。

代码示例

#!/usr/bin/env bash
set -euo pipefail

retry() {
  local max_attempts="$1"; shift
  local delay=1
  local attempt=0
  until "$@"; do
    attempt=$((attempt + 1))
    if (( attempt >= max_attempts )); then
      echo "retry: giving up after ${attempt} attempts" >&2
      return 1
    fi
    echo "retry: attempt ${attempt} failed, sleeping ${delay}s" >&2
    sleep "$delay"
    delay=$((delay * 2))
  done
}

# 用法示例:最多 5 次,命令失败时按 1s、2s、4s、8s 退避
retry 5 curl -fsS --max-time 10 https://api.example.com/health