Bash忽略特定命令的错误

我使用以下选项

set -o pipefail
set -e

在bash脚本中停止执行错误。我有大约100行脚本正在执行,我不想检查脚本中每一行的返回代码。

但是对于一个特定的命令,我想忽略错误。我该怎么做?

477744 次浏览

解决方案:

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

只需在要忽略错误的命令后添加|| true

更简洁地说:

! particular_script

POSIX规范关于set -e(强调我的):

当此选项打开时,如果一个简单的命令由于Shell错误的后果中列出的任何原因而失败,或者返回一个退出状态值>0,并且不是复合列表的一部分,然后是同时,直到,或者如果关键字,并且不是AND或OR列表的一部分,并且不是管道前面有!保留字,那么shell将立即退出。

而不是“返回true”,您还可以使用“noop”或null实用程序(如POSIX规格中所述):并只是“什么都不做”。您将节省一些字母。:)

#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."

不要停止并保存退出状态

以防万一,如果您希望您的脚本在特定命令失败时不停止,并且您还想保存失败命令的错误代码:

set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE

在使用CLI工具时,我一直在使用下面的片段,我想知道是否存在某些资源,但我不关心输出。

if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
echo "none exist actually exist!"
fi

虽然|| true是首选,但您也可以这样做

var=$(echo $(exit 1)) # it shouldn't fail

我有点喜欢这个解决方案:

: `particular_script`

执行返回刻度之间的命令/脚本,并将其输出馈送到命令“:”(相当于“true”)

$ false
$ echo $?
1
$ : `false`
$ echo $?
0

编辑:修复丑陋的错字

如果您想防止脚本失败,请收集返回代码:

command () {
return 1  # or 0 for success
}


set -e


command && returncode=$? || returncode=$?
echo $returncode

无论命令成功还是失败,都会收集returncode

我找到了另一种方法来解决这个问题:

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

您可以通过set +e关闭错误失败,这现在将忽略该行之后的所有错误。完成后,如果您希望脚本在任何错误上再次失败,您可以使用set -e

应用set +e后,当找不到文件时,find不会再失败整个脚本。同时,错误消息 fromfind仍然打印,但整个脚本继续执行。因此,如果这导致问题,很容易调试。

这对CI和CD很有用(例如在GitHub Actions中)。

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/command> || true

以下结构可用于脚本步骤的额外操作/故障排除和额外的流控制选项:

if <particular_script/command>
then
echo "<particular_script/command> is fine!"
else
echo "<particular_script/command> failed!"
#exit 1
fi

如果需要,我们可以制动进一步的动作和exit 1