如果特定命令失败,请不要中止脚本

dan*_*ast 4 bash

我正在运行我的脚本:

#!/bin/bash -eu
Run Code Online (Sandbox Code Playgroud)

如果出现问题,会在需要时中止脚本.但有时我希望其中一个命令最终失败,我想告诉bash忽略失败条件.在make你可以忽略一个命令与得心应手的状态:

-command
Run Code Online (Sandbox Code Playgroud)

有类似的东西bash吗?想到的唯一一件事就是丑陋:

set +e
command
set -e
Run Code Online (Sandbox Code Playgroud)

Ini*_*ian 9

你可以在命令失败时做一个no-op或者设置一个明确的真实条件

command || true
Run Code Online (Sandbox Code Playgroud)

或者对于无操作

command || :
Run Code Online (Sandbox Code Playgroud)

这样做会强制命令列表(甚至是管道)在失败时返回退出状态0.看到

true | false
echo $?
1
true | false || true
echo $?
0
true | false || :
echo $?
0
Run Code Online (Sandbox Code Playgroud)


fed*_*qui 5

只需!在命令前添加a,以使其在使用以下命令运行时退出状态不会使脚本退出e

! command
Run Code Online (Sandbox Code Playgroud)

正如在什么意思中看到的!在Shell中执行命令之前?,使! command否定给定命令的退出状态,并与一起使用set -e,可防止shell退出该行上的退出结果。

来自Bash参考手册?管道

管道中的每个命令都在其自己的子Shell中执行。管道的退出状态是管道中最后一条命令的退出状态(...)。如果保留字为“!” 在管道之前,退出状态是如上所述退出状态的逻辑取反。在返回值之前,shell等待管道中的所有命令终止。

然后,我们获得有关4.3.1 The setBuiltin的信息:

-e

如果可能由单个简单命令(请参见简单命令),列表(请参见列表)或复合命令(请参见复合命令)组成的管道(请参见“管道”)返回非零状态,则立即退出。如果失败的命令紧随一段时间或直到关键字,if语句中的测试部分,&&或||中执行的任何命令的一部分之后,命令列表中的一部分,则外壳程序不会退出。列出除最后一个&&或||之后的命令,管道中除最后一个命令之外的任何命令,或者如果该命令的返回状态用!反转!

一起,并引用我自己的答案:

当你有:

set -e
! command1
command2
Run Code Online (Sandbox Code Playgroud)

您正在做的是绕过。中的set -e标志command1。为什么?

  • 如果command1运行正常,它将返回零状态。!会否定它,但set -e不会触发退出,因为如上所述,它来自返回状态,并以!取反。
  • 如果command1失败,它将返回非零状态。!会将其取反,因此该行最终将返回零状态,并且脚本将正常继续。