linux shell 通过非零退出码模拟异常,推荐用1–127自定义错误码(如1通用错、2校验失败),配合set -e、$?捕获、die函数和统一exit点提升健壮性与可观测性。

Linux Shell 脚本本身没有“异常”概念,但可通过退出码(exit code)模拟异常语义——用非零值代表不同错误类型,并配合 set -e 和显式 return/exit 实现可控的“抛出”行为。
定义并返回自定义错误码
函数或主逻辑中,用 return N(在函数内)或 exit N(终止整个脚本)主动返回特定非零值。推荐使用 1–127 范围(128+ 通常被信号占用):
-
return 1:通用错误(如参数缺失、命令执行失败) -
return 2:输入校验失败(如文件不存在、目录不可写) -
return 3:依赖缺失(如jq未安装) -
return 4:资源冲突(如锁文件已存在) -
return 5:业务逻辑拒绝(如备份目标空间不足)
在调用处捕获并响应错误码
调用函数后立即检查 $?,根据返回值做分支处理,避免静默忽略:
download_config() {
curl -f -o /tmp/config.json https://api.example.com/conf || return 12
[ -s /tmp/config.json ] || return 13
return 0
}
download_config
case $? in
0) echo "配置获取成功" ;;
12) echo "网络请求失败" >&2 ;;
13) echo "配置内容为空" >&2 ;;
*) echo "未知错误" >&2 ;;
esac
配合 set -e + 显式错误包装提升健壮性
脚本开头启用严格模式,并为关键步骤封装带错误码的检查逻辑:
set -e -u -o pipefail
die() {
local code=${2:-1}
echo "ERROR [$code] at line $1: $3" >&2
exit "$code"
}
# 使用方式:
[[ -d /backup ]] || die "$LINENO" 20 "备份目录缺失"
这样既保持错误可读性,又让每处失败都携带明确上下文与编码,便于日志归因和监控识别。
统一出口与日志标记增强可观测性
主逻辑用子 shell 或函数封装,最终统一输出带标签的日志并返回标准码:
main() {
if ! do_backup; then
echo "Backup failed with code $?" | logger -t "backup-script[ERR]"
exit "$?"
fi
logger -t "backup-script[OK]" "Success"
exit 0
}
main "$@"
所有错误路径最终都导向一个 exit 点,确保退出码不被覆盖,也方便集中上报(如通过 curl 推送告警)。











