617

我正在使用以下选项

set -o pipefail
set -e

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

但是对于一个特定的命令,我想忽略该错误。我怎样才能做到这一点?

4

12 回答 12

1015

解决方案:

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
于 2012-06-27T17:37:44.240 回答
220

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

于 2012-06-27T17:37:45.160 回答
153

不要停止并保存退出状态

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

set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE
于 2017-08-17T08:14:44.357 回答
71

更简洁:

! particular_script

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

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

于 2015-04-21T23:13:37.683 回答
54

除了“返回 true”,您还可以使用“noop”或 null 实用程序(如POSIX 规范中所述):并且只是“什么也不做”。你会省下几封信。:)

#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."
于 2016-11-17T08:51:41.420 回答
11

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

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

set -e

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

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

于 2019-09-10T10:33:41.890 回答
8

从这里没有解决方案对我有用,所以我找到了另一个解决方案:

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 很有用。这样会打印错误消息,但整个脚本会继续执行。

于 2020-02-23T13:35:23.400 回答
8

感谢上面的简单解决方案:

<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如果需要,我们可以阻止进一步的行动。

于 2020-05-20T13:28:21.133 回答
4
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
于 2020-03-25T03:25:27.490 回答
2

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

if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
    echo "none exist actually exist!"
fi
于 2018-06-23T22:12:33.163 回答
1

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

: `particular_script`

执行反引号之间的命令/脚本,并将其输出馈送到命令“:”(相当于“真”)

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

编辑:修正了丑陋的错字

于 2019-05-21T08:56:57.967 回答
0

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

var=$(echo $(exit 1)) # it shouldn't fail
于 2019-04-25T15:17:27.440 回答