5.7.4 错误处理、退出码与幂等性

错误处理、退出码与幂等性#

错误处理、退出码与幂等性是自动化脚本稳定运行的核心。脚本应在失败时及时中止并输出可定位的错误信息;退出码要与外部调度系统一致;幂等性确保重复执行不会产生副作用。

文章图片

关键原则与命令解释#

  • set -euo pipefail:命令失败立刻退出、未定义变量报错、管道任一失败即失败。
  • trap '...' ERR EXIT:捕获错误与退出事件,集中清理与告警。
  • exit N:0 成功;非 0 失败,建议自定义含义并文档化。

可执行示例:严格模式 + 错误处理 + 幂等写配置#

#!/usr/bin/env bash
# 文件: /usr/local/bin/app_config.sh

set -euo pipefail

LOG=/var/log/app_config.log
CONF=/etc/myapp/app.conf
LOCK=/var/run/app_config.lock

die() { echo "[ERROR] $*" | tee -a "$LOG" >&2; exit 1; }
info(){ echo "[INFO] $*" | tee -a "$LOG"; }

cleanup() { rm -f "$LOCK"; }
trap 'die "脚本执行失败,行号: $LINENO"' ERR
trap cleanup EXIT

# 依赖检查
command -v flock >/dev/null 2>&1 || die "缺少依赖: flock"
command -v sha256sum >/dev/null 2>&1 || die "缺少依赖: sha256sum"

# 加锁避免并发
exec 200>"$LOCK"
flock -n 200 || die "已有实例在运行"

# 幂等创建目录
install -d -m 0755 /etc/myapp
install -d -m 0755 /var/log

# 幂等写入配置:先生成临时文件,再原子替换
tmp=$(mktemp)
cat >"$tmp" <<'EOF'
[app]
port=8080
log_level=info
EOF

# 如果内容无变化则不写入
if [ -f "$CONF" ]; then
  oldsum=$(sha256sum "$CONF" | awk '{print $1}')
  newsum=$(sha256sum "$tmp"  | awk '{print $1}')
  if [ "$oldsum" = "$newsum" ]; then
    info "配置无变化,跳过写入"
    exit 0
  fi
fi

# 原子替换
mv -f "$tmp" "$CONF"
info "配置已更新: $CONF"

exit 0

运行与预期效果

sudo /usr/local/bin/app_config.sh
# 预期输出:配置已更新或配置无变化
# 退出码:0

退出码示例与解释#

#!/usr/bin/env bash
# 文件: /usr/local/bin/check_env.sh

set -euo pipefail
command -v curl >/dev/null 2>&1 || { echo "缺少 curl"; exit 127; }
[ $# -eq 1 ] || { echo "参数错误: 需要1个URL"; exit 2; }

url="$1"
if ! curl -fsS --max-time 3 "$url" >/dev/null; then
  echo "访问失败: $url"
  exit 10
fi

echo "环境检查通过"
exit 0

排错与定位#

  • 症状:脚本无日志且直接退出
    排查:确认 set -e 是否导致中途退出,可临时加 set -x 追踪。
    bash bash -x /usr/local/bin/app_config.sh
  • 症状:并发执行导致配置损坏
    排查:确认 flock 是否生效,检查锁文件权限。
    bash ls -l /var/run/app_config.lock
  • 症状:管道命令中间失败但未退出
    排查:确保使用 set -o pipefail
    bash set -o | grep pipefail

练习#

  1. app_config.sh 修改为写入 /etc/myapp/app.conf 前先检测端口是否被占用(如 8080),占用则退出码为 11。
  2. check_env.sh 中加入重试机制(最多 3 次),并确保重试过程不破坏幂等性。
  3. 自定义退出码表(0、2、10、11、127),写入脚本头部注释并在日志中输出。