Linux Shell 脚本中除零错误不触发 SIGFPE,应使用 trap ERR 捕获;$((a/b)) 静默失败,需用 ((...)) 或 let 才返回错误状态;主动检查除数更健壮。

Linux Shell 脚本本身不触发 SIGFPE 信号来响应除零错误,这是关键前提。Bash 等 shell 解释器在执行算术扩展(如 $((a / b)))时,遇到除零会直接报错并退出,不会向进程发送 SIGFPE,因此 trap SIGFPE 在纯 shell 脚本中完全无效。
真正能捕获的,是 shell 层面的命令失败事件,而非硬件异常信号。
✅ 正确做法:用 trap ERR 捕获算术失败
Bash 提供 ERR 伪信号,当任意命令返回非零退出状态时触发。而 let、((...)) 或 $((...)) 在除零时会返回状态码 1,正好可被 trap ERR 捕获。
#!/bin/bash
# 启用 errtrace,确保函数内错误也能触发 trap
set -o errtrace
# 定义错误处理逻辑
handle_divzero() {
echo "❌ 算术错误:检测到除零操作" >&2
echo " 当前行号:$LINENO" >&2
echo " 上一命令:$BASH_COMMAND" >&2
exit 1
}
trap handle_divzero ERR
# 示例:触发除零
a=10; b=0
echo "计算 $a / $b..."
(( result = a / b )) # 这里失败,触发 ERR trap⚠️ 注意:
$((a / b))单独写不会报错(它只是展开为空),必须用(( ... ))或let才会实际执行并返回错误状态。
✅ 主动检查除数,预防优于补救
更健壮的方式是在运算前判断:
safe_div() {
local num=$1 den=$2
if [[ $den == 0 ]]; then
echo "错误:除数不能为零(输入:$num / $den)" >&2
return 1
fi
echo $(( num / den ))
}
# 使用
if ! result=$(safe_div 10 0); then
exit 1
fi这样可控、可测试、不依赖 trap,也避免了 ERR trap 可能误捕其他非算术错误。
❌ 常见误区澄清
-
trap 'echo boom' SIGFPE—— 无效。Shell 不发 SIGFPE,该 trap 永远不会执行。 -
echo $((10 / 0))—— 不报错也不触发 trap,只输出空字符串(静默失败)。 - 依赖
set -e单独处理 ——set -e对$((...))无效(它不是命令),但对((...))有效。
✅ 补充:调试定位出错位置
结合 set -o functrace 和 LINENO,可精确定位:
trap 'echo "? ERR at line $LINENO: $BASH_COMMAND" >&2; exit 1' ERR set -o functrace # 让函数内错误也触发 ERR
这样即使错误发生在函数内部,也能打出准确行号和上下文。
不复杂但容易忽略。


















