bash - Bash set -e 没有立即退出 pipefail
问题描述
set -eo pipefail
commandThatFails || exitFunction
exitFunction
所以这个脚本运行 exitMethod 两次......我认为set -e
在任何非零退出代码上立即退出,并set -o pipefail
确保在管道期间任何失败都是最终退出状态代码而不是最近的命令?
因此我想:
- 命令失败
- 执行退出函数
- set -o pipefail 在第一个命令失败时返回非零退出代码
- set -e 检测到非零退出代码并立即退出
在文档中它指出:
如果失败的命令是紧跟在 while 或 until 关键字之后的命令列表的一部分、if 语句中测试的一部分、在 && 或 || 中执行的任何命令的一部分,则 shell 不会退出 列出除了最后一个 && 或 || 之后的命令,管道中除最后一个之外的任何命令,或者命令的返回状态是否用 ! 反转。如果子 shell 以外的复合命令由于在忽略 -e 时命令失败而返回非零状态,则 shell 不会退出。如果设置了 ERR 陷阱,则会在 shell 退出之前执行。
我认为 exitfunction 是command following the final ||
这样,因此会被计算并立即退出。
我可以通过以下方式解决问题:
commandThatFails || { exitFunction; exit 1; }
但这似乎不是更优雅的处理方式,任何想法都值得赞赏!
解决方案
||
是流控制操作符,而不是管道组件。pipefail
对它没有影响。
如果set -e
导致流控制操作员退出,那么您将永远无法else
让脚本的分支在其处于活动状态时运行;这将是完全没用的。
出于这个原因,&&
并为他们的左侧||
抑制行为,就像为 抑制该行为一样。set -e
if condition; then success; else fail; fi
condition
一般做法是进行exitFunction
实际调用exit
,因此您可以编写:
die() {
rc=$?
(( $# )) && printf '%s\n' "$*" >&2
exit "$(( rc == 0 ? 1 : rc ))"
}
commandThatFails || die "commandThatFails failed"
...但是如果您想先调用其他内容,是的,您需要使用分组,就像您在问题中所做的那样。
推荐阅读
- ignite - 创建缓存后立即触发分区丢失
- linux - Prometheus 记录规则保持最大值 (rate of counter)
- amazon-cognito - 增加 AWS Cognito 会话令牌
- java - 每次重启后都会添加片段(Android)
- postgresql - st_dwithin 忽略 Postgresql 要点索引
- async-await - 在下一个 js 中无限的异步函数执行
- linux - 如何在终端管道请求中从其名称的一部分获取和使用 docker 容器 ID?
- html - 如何根据离子内容的高度有条件地扩展元素?
- angular - Ionic Angular InAppBrowser 重定向帖子
- angular - Angular 单元测试失败:没有 WebSocketAPI 的提供者