首页 > 解决方案 > 为什么要使用 set errexit 而不是 errtrace

问题描述

使用 errtrace 我有更好的结果:

#!/usr/bin/env bash

set -Euxo
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR

...dosomething

failure(){
  local lineno=$1
  local msg=$2
  report="Failed at $lineno: $msg"
  email_report
  exit 1
}

...bashscript continued

如果我使用 set -e (errexit),

trap 'failure ${LINENO} "$BASH_COMMAND"' EXIT

我的 LINENO 始终为 1,与 errtrace 一样,它显示正确的行号,我只是告诉脚本退出 failure() 函数。因此,似乎我得到了相同的结果,即在捕获错误时停止脚本执行,并报告发生错误的正确行号。

标签: bashexception

解决方案


根据bash的手册:

陷阱[ -lp ] [[ arg ] sigspec ...]

[…]

如果sigspecEXIT (0),则在退出 shell 时执行命令arg 。如果sigspecDEBUG,则命令arg在每个简单命令for命令、case命令、select命令、每个算术for命令之前执行,并且在第一个命令在 shell 函数中执行之前执行 (...)。有关它对DEBUG陷阱的影响的详细信息,请参阅内置shopt的extdebug选项的描述。如果sigspecRETURN每次使用. 内置完成执行。

如果sigspecERR,则只要简单命令具有非零退出状态,就会执行命令arg ,但须符合以下条件。如果失败的命令是紧跟在whileuntil关键字之后的命令列表的一部分、if语句中的测试的一部分、在&&||中执行的命令的一部分,则不会执行ERR陷阱。列表,或者如果命令的返回值通过! . 这些与errexit选项遵循的条件相同。

进入 shell 时忽略的信号不能被捕获、重置或列出。未被忽略的捕获信号在创建时会在子shell 或子shell 环境中重置为其原始值。如果任何sigspec无效,则返回状态为 false;否则陷阱返回真。

设置-e

[…] ERR上的陷阱(如果设置)在 shell 退出之前执行。此选项分别适用于 shell 环境和每个子 shell 环境 (...),并可能导致子 shell 在执行子 shell 中的所有命令之前退出。

退出[n]

[…]在 shell 终止之前执行EXIT上的陷阱。


推荐阅读