【发布时间】:2022-01-25 06:59:21
【问题描述】:
我正在使用以下选项
set -o pipefail
set -e
在 bash 脚本中停止执行错误。我有大约 100 行脚本正在执行,我不想检查脚本中每一行的返回码。
但是对于一个特定的命令,我想忽略错误。我该怎么做?
【问题讨论】:
我正在使用以下选项
set -o pipefail
set -e
在 bash 脚本中停止执行错误。我有大约 100 行脚本正在执行,我不想检查脚本中每一行的返回码。
但是对于一个特定的命令,我想忽略错误。我该怎么做?
【问题讨论】:
这里没有适合我的解决方案,所以我找到了另一个解决方案:
set +e
find "./csharp/Platform.$REPOSITORY_NAME/obj" -type f -iname "*.cs" -delete
find "./csharp/Platform.$REPOSITORY_NAME.Tests/obj" -type f -iname "*.cs" -delete
set -e
这对 CI 和 CD 很有用。这样会打印错误消息,但整个脚本会继续执行。
【讨论】:
感谢上面的简单解决方案:
<particular_script/command> || true
以下构造可用于脚本步骤的附加操作/故障排除和附加流控制选项:
if <particular_script/command>
then
echo "<particular_script/command> is fine!"
else
echo "<particular_script/command> failed!"
#exit 1
fi
如果需要,我们可以阻止进一步的操作和exit 1。
【讨论】:
output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
echo $output
echo $exit_status
使用它创建日志文件的示例
log_event(){
timestamp=$(date '+%D %T') #mm/dd/yy HH:MM:SS
echo -e "($timestamp) $event" >> "$log_file"
}
output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
if [ "$exit_status" = 0 ]
then
event="$output"
log_event
else
event="ERROR $output"
log_event
fi
【讨论】:
解决办法:
particular_script || true
例子:
$ cat /tmp/1.sh
particular_script()
{
false
}
set -e
echo one
particular_script || true
echo two
particular_script
echo three
$ bash /tmp/1.sh
one
two
three 永远不会被打印出来。
另外,我想补充一点,当pipefail 开启时,
shell 认为整个管道具有非零退出代码就足够了
当管道中的命令之一具有非零退出代码时(pipefail 关闭,它必须是最后一个)。
$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0
【讨论】:
-e 属性时,“shell 不会退出”“如果失败的命令是紧跟在 while 或 until 关键字之后的命令列表的一部分,则if 语句中的测试,在 && 或 || 列表中执行的任何命令的一部分,除了最后一个 && 或 || 之后的命令,管道中除最后一个以外的任何命令,或者如果命令的返回状态正在与 ! 反转。"
(ldd $2/bin/* || true) | grep "not found" | wc -l 当 ldd 返回失败时脚本在此行之后终止
(ldd $2/bin/* || true) | grep "not found" | wc -l || true
set -o pipefail。当grep 什么都没有找到时,它返回非零退出代码,shell 认为整个管道都有非零退出代码就足够了。
如果您想防止脚本失败并收集返回码:
command () {
return 1 # or 0 for success
}
set -e
command && returncode=$? || returncode=$?
echo $returncode
returncode无论命令成功还是失败都会被收集。
【讨论】:
不要停止,还要保存退出状态
以防万一您希望脚本在特定命令失败时不停止,并且您还想保存失败命令的错误代码:
set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE
【讨论】:
command 成功,需要运行 || 之后的内容。将其读作:如果command 失败,则执行EXIT_CODE=$?。您可能可以只做command || echo "$?" 或使用“陷阱”进行更详细的调试。看到这个->stackoverflow.com/a/6110446/10737630
我有点喜欢这个解决方案:
: `particular_script`
执行反引号之间的命令/脚本,并将其输出馈送到命令“:”(相当于“true”)
$ false
$ echo $?
1
$ : `false`
$ echo $?
0
编辑:修正了难看的错字
【讨论】:
虽然|| true 是首选,但你也可以这样做
var=$(echo $(exit 1)) # it shouldn't fail
【讨论】:
我在使用 CLI 工具时一直在使用下面的 sn-p,我想知道是否存在某些资源,但我不关心输出。
if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
echo "none exist actually exist!"
fi
【讨论】:
if [ -r not_exist ]
除了“返回 true”,您还可以使用“noop”或 null 实用程序(如 POSIX specs 中所述): 并且只是“什么也不做”。你会省下几封信。 :)
#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."
【讨论】:
更简洁:
! particular_script
来自POSIX specification 关于set -e(强调我的):
启用此选项时,如果简单命令由于 Shell 错误的后果中列出的任何原因而失败或返回退出状态值 >0,并且在一段时间、直到或如果之后不属于复合列表的一部分关键字,并且不是 AND 或 OR 列表的一部分,也不是前面有 ! 的管道 保留字,则shell将立即退出。
【讨论】:
-e 失败脚本。
!无论如何都会阻止shell退出。 This script 运行时显示消息Still alive!,表示脚本运行完成。您是否看到了不同的行为?
if 子句中并解决了问题。
particular_script 的返回值,但如果 particular script 是一个我确实不想要的函数忽略函数内语句的返回值。 || 解决方案将忽略 particular_script 函数体内的所有返回码,这通常不是您想要的 (stackoverflow.com/a/37191242/985292)。
只需在要忽略错误的命令后添加|| true。
【讨论】:
set -e 并尝试捕获错误消息时很重要:例如set -e; TEST=$(foo 2>&1 || true); echo $TEST
set -e,将找不到的bash命令从stderr重定向到$TEST。这如何保留响应代码?
set -e; TEST=$(foo 2>&1) || printf "ERROR $?: $TEST\n"