任何命令执行失败时中止 Shell 脚本
概述
通过使用 Bash 脚本,我们可以访问强大的编程语言。编写此类脚本可以高效地依次运行多个命令。即使一个命令失败,其他命令仍会执行。
我们将学习如何添加一些保护措施以避免这些错误发生。示例代码已在 Bash 中测试过。它们也适用于其他兼容 POSIX 的 Shell 环境。
问题
首先,让我们来看看 Bash 默认如何处理错误消息。假设我们有一个名为"hello.sh"的简单 shell 脚本,它会打印出单词"Hello",后面跟着单词"World"。
#!/bin/bash echo hello echo world
运行该脚本会得到预期结果 -
$ ./hello.sh hello world
接下来,我们将添加一条注定会失败的语句。
#!/bin/bash echo hello cat non-existing-file echo world
执行该脚本后,将产生输出。执行不会停止,但仍然会输出"world" -
$ ./hello.sh hello cat: non-existing-file: No such file or directory world
我们的脚本也得到了一个 0 的退出代码,这表明一切顺利。
$ echo $? 0
第一次出错时退出
如果希望脚本中的任何命令失败时都退出,可以使用 set -e 选项。此选项指示脚本在脚本中的任何命令以非零状态退出时立即退出。
以下是如何在 Shell 脚本中使用 set -e 选项的示例 -
#!/bin/bash # Set the -e option set -e # Run some commands echo "Running command 1" command1 echo "Running command 2" command2 echo "Running command 3" command3 # The script will exit if any of the commands above fail echo "All commands completed successfully"
在此示例中,如果 command1、command2 或 command3 中的任何命令失败(即以非零状态退出),脚本将立即退出,并且不会执行其余命令。
请注意,set -e 选项仅适用于由 shell 直接运行的命令(例如,echo、command1 等),而不适用于由 shell 扩展运行的命令(例如,$(command))。要使 set -e 选项应用于所有命令(包括由 shell 扩展运行的命令),可以将 set -o pipefail 选项与 set -e 结合使用。
使用 Pipefail
遗憾的是,如果您的脚本包含管道语句,此解决方案将不起作用。例如,如果我们将前两个命令(失败的命令)通过管道连接在一起,从失败的命令开始,就会收到一条错误消息。
#!/bin/bash set -e cat non-existing-file | echo hello echo world
即使我们使用了 set -e,以下命令仍然输出 -
$ ./hello.sh hello cat: non-existing-file: No such file or directory world
如果我们想运行多个命令而不让任何一个命令失败,我们可以在第一个命令中添加 -o pipefail 选项。
#!/bin/bash set -eo pipefail cat non-existing-file | echo hello echo world
我们告诉 bash,如果管道内部发生错误,它应该停止并报告管道中最后一个命令的退出代码。
$ ./hello.sh hello cat: non-existing-file: No such file or directory
这会导致我们之前见过的非零返回码 -
$ echo $? 1
结论
我们已经学习了如何使用命令"exit"在发生错误时立即终止shell脚本。我们还添加了 -o pipefail 选项,以便管道的行为与之前相同。请务必在shell脚本的开头添加 set -eo pipeline fail 选项。
相关文章
有用资源
linux 参考教程 - 该教程包含有关 linux 的更多信息:https://www.cainiaomax.com/linux/

