一次 Bash 脚本调试经历:`set -e` 与 bru run 返回码的问题

0 阅读1分钟

WechatIMG132.jpg

🐛 一次 Bash 脚本调试经历:set -e 与 bru run 返回码的问题

在一次日常的脚本自动化中,我遇到了一个看似简单但实则隐藏坑点的问题。最终的 root cause 出乎意料,记录下来希望对你也有帮助。


🧩 背景

我们在使用 bash 脚本执行一系列任务,过程中使用了一个内部工具命令 bru run 来执行测试任务。脚本结构大致如下:

#!/bin/bash
set -e

bru run some-task

if [ $? -eq 0 ]; then
  echo "Run succeeded."
else
  echo "Run failed."
  exit 1
fi

脚本逻辑是:

  • 启用 set -e 来确保脚本在遇到任何非 0 返回码时立即退出
  • 执行 bru run
  • 根据返回码判断是否继续处理

结果:脚本总是在 bru run 后直接退出,后续逻辑根本不会执行


❗问题分析

我们观察到:

  • bru run 实际返回值为 1,这在它的语义下是一个正常情况,比如任务执行中有失败但仍生成报告;
  • 由于 set -e 的开启,bash 在遇到 bru run 返回非 0 的时候就立刻退出脚本,根本没有机会进入后续的 if 判断
  • 此外,即使关闭 set -e,下面这种判断也值得反思:
if [ $? -eq 0 ]; then

因为如果你允许某些非 0 返回作为“正常情况”,就需要更细粒度的控制错误处理逻辑。


✅ 正确做法

目标:

  • 即使 bru run 返回 1,脚本也要能继续往下执行;
  • 但仍然对非预期错误保持敏感;
  • 避免 set -e 误伤“合法失败”。

方法一:局部关闭 set -e,手动处理错误

#!/bin/bash
set -e

set +e
bru run some-task
result=$?
set -e

if [ $result -eq 0 ] || [ $result -eq 1 ]; then
  echo "bru run finished with code $result (acceptable)"
else
  echo "bru run failed with unexpected code $result"
  exit 1
fi

echo "Continue processing..."

这样你可以:

  • 保留 set -e 的大部分保护作用;
  • bru run 的特殊行为做例外处理。

方法二:完全不使用 set -e,显式判断关键命令结果

如果你脚本中类似的命令很多,不如完全不依赖 set -e,自己控制每一步:

#!/bin/bash

bru run some-task
result=$?
if [ $result -ne 0 ] && [ $result -ne 1 ]; then
  echo "Unexpected error code: $result"
  exit 1
fi

echo "Report generated, continuing..."

🎯 结语

这次问题让我意识到:

  • 并不是所有非 0 返回码都意味着“错误”,上下文语义很重要;
  • set -e 是一把双刃剑,虽然能简化错误处理,但遇到特殊返回值时容易踩坑;
  • 写脚本时要清楚每个命令的“返回语义”,才能避免误判。

希望这个经验能帮你在自动化任务中少踩坑!


💬 如果你也遇到过类似的情况,欢迎留言交流!