当条件失败时如何停止 bash 脚本?

kos*_*sol 13 command-line bash scripts

这里显示在一行中使用||&&来连接命令的执行:如何检查 bash 脚本中的 apt-get 错误?

如果某个条件失败,我试图停止脚本执行,

例如

false || echo "Obvious error because its false on left" && exit
Run Code Online (Sandbox Code Playgroud)

在这里它打印Obvious error because its false on the left并退出我想要的控制台。

true || echo "This shouldn't print" && exit
Run Code Online (Sandbox Code Playgroud)

在这里,没有回显打印但exit命令也运行,即控制台关闭,该exit命令不应该运行,因为右侧的回显命令没有执行吗?或者默认情况下,&&运算符左侧的语句被认为是错误的?

编辑:我之前应该提到它,我的目的是回应错误并在不清楚时退出。对于我在使用 && 和 || 对条件进行分组时捕获错误的具体情况,@bodhi.zazen 答案解决了这个问题。

@takatakatek 的回答使流程控制更加清晰,bash 指南链接非常好

@muru answer 很好地解释了为什么不使用 set -e 如果您希望使用 perl 和 trap 的替代方法抛出自定义错误消息,我认为这是一种更健壮的方法,并且可以从我的第二个 bash 脚本开始使用它!

tak*_*tek 15

问题是 || 和 && 仅在条件失败时跳过命令链的一个后续节。如果你写出一个完整的块结构,它是完全合理的。你写的变成了这样:

if ! true ; then
   echo "This shouldn't print"
else
   exit
fi
Run Code Online (Sandbox Code Playgroud)

你想要的是这个:

if ! true ; then
   echo "This shouldn't print"
   exit
fi
Run Code Online (Sandbox Code Playgroud)

当您使用 Bash 的快捷条件运算符时,最好避免混合使用它们。在你写的时候,逻辑更容易理解,你的读者会欣赏你的好风格。

  • 是的,在我看来,这更多的是应该如何编写 bash 中的条件反射 (2认同)

Pan*_*her 12

你可能想要(如 steeldriver 指出的)

true || { echo "This shouldn't print" && exit; }
Run Code Online (Sandbox Code Playgroud)

否则,您的脚本会一次读取一个条件

a 或 b 然后退出

我想你想要 a or (b and exit) ?

  • 实际上,您*必须*使用 `{ ... ; }`(如@steeldriver 建议的那样),否则`exit` 只退出子shell,父shell 继续执行脚本。 (4认同)

agg*_*877 8

您可以使用以下命令启动脚本:

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

-e脚本退出的那一刻东西返回false保证(或任何非零数字)。然后可以避免特定的故障something || true

或者,如果您想将错误检查推迟到脚本的后面,您可以使用set -e

#!/bin/bash
false  # script continues happily
set -e
false  # script stops
Run Code Online (Sandbox Code Playgroud)


mur*_*uru 7

出错失败的最简单方法是使用 bash 的-e选项(set -e/bin/bash -e在 shebang 中)。但是,这并不容易发送自定义错误消息。有几个习语可能会使它更简单:

die à la Perl

Perl 有一个非常方便的die命令,它可以向 stderr 打印一条消息并引发异常,这通常会导致脚本终止。你可以模仿这个:

die () {
  ret=$?
  print "%s\n" "$@" >&2
  exit "$ret"
}

false || die "Obvious error because its false on left"
true || die "This shouldn't print"
Run Code Online (Sandbox Code Playgroud)

trap ERR

trap <command>命令可用于在接收到信号、退出脚本 ( trap ... EXIT) 或命令返回错误 ( trap ... ERR)时运行命令。所以像:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR
Run Code Online (Sandbox Code Playgroud)

然后:

ERR_MSG="Obvious error because its false here"
false
ERR_MSG="This shouldn't print"
true
Run Code Online (Sandbox Code Playgroud)

无论哪种情况,我都建议至少使用exit 1, 来指示脚本失败。一个普通的exit将使用前一个命令的退出状态,在这些情况下是echoorprintf命令,通常会成功。像我在这里所做的那样保存失败命令的退出状态将是一个很好的选择。