bash - Bash:设置“set -e”时捕获退出代码而不是中止?
问题描述
在大多数情况下,我更喜欢我的脚本在遇到意外错误时终止,因此通常以set -e -u -E -o pipefail
.
但是,有时我需要捕获单个调用的退出代码而不是终止。这导致了类似的结构
# (1) Verbose. Breaks when moved between scripts
# with different global -e setting.
set +e
COMMAND WITH A LOT OF ARGUMENTS \
| AND MAYBE EVEN PIPES \
| MAYBE OVER MANY LINES
exitCode=$?
set -e
# (2) Verbose.
if COMMAND WITH A LOT OF ARGUMENTS \
| AND MAYBE EVEN PIPES \
| MAYBE OVER MANY LINES
then exitCode=$?
else exitCode=$?
fi
# (3)
exitCode=0
COMMAND WITH A LOT OF ARGUMENTS \
| AND MAYBE EVEN PIPES \
| MAYBE OVER MANY LINES \
|| exitCode=$?
# (4) Brittle, must not mix up order of && and ||
COMMAND WITH A LOT OF ARGUMENTS \
| AND MAYBE EVEN PIPES \
| MAYBE OVER MANY LINES \
&& exitCode=$? || exitCode=$?
# (5), doesn't work with `set -o pipefail`
COMMAND WITH A LOT OF ARGUMENTS \
| AND MAYBE EVEN PIPES \
| MAYBE OVER MANY LINES | cat
exitCode=$PIPESTATUS
# (6) Requires maintaining a function across scripts.
captureExitCode COMMAND WITH A LOT OF ARGUMENTS \
| AND MAYBE EVEN PIPES \
| MAYBE OVER MANY LINES
# where
captureExitCode() {
# any of the above constructs with "$@" as command
}
所有这些要么很冗长,要么在视觉上有些难以解析,尤其COMMAND ...
是在多行管道命令的情况下。至少,他们没有很好地传达他们的意图。在函数的情况下,captureExitCode
必须跨脚本复制。
是否有一些不那么冗长的内置习语来捕获退出代码?
解决方案
在子 shell 中运行有问题的命令并禁用errexit
:
(
set +e
run buggy code failing without proper error handling
)
exitcode=$?
例子:
#! /bin/bash
set -e
if ( set +e
false
)
then
echo success
else
echo failure
fi
顺便说一句:当您以这种方式编写管道时,您不需要反引号:
echo abc |
tr a x |
sed 's/^x/y/'
推荐阅读
- python - BeautifulSoup webscrape .asp 只搜索列表中的最后一个
- r - 在 R 中提取具有唯一 id 变量的一行
- c - 为什么结构指针有错误的值
- r - 在R中按组计算日期间隔,考虑到当日期重叠时只计算一次
- r - 如何避免在 shinyapps.io 服务器上发布源代码?
- regex - 找不到正则表达式模式来拉特定列
- spring - Couchbase 文档到期不适用于 spring-data-couchbase:.4.0.3.RELEASE
- laravel - Laravel Sanctum + Nuxt JS 我无法通过 CORS
- ios - 是否可以通过蓝牙从 iOS 设备向 iOS 设备发送一次 NSData 实例?
- kotlin - 为什么调用lifecycleScope.launch { //interact with database } 有效(不改变协程上下文),是否创建了一个新线程?