任何命令失败都会中止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
第一个错误就退出
如果希望在脚本中的任何命令失败时使shell脚本退出,可以使用`set -e`选项。此选项告诉shell在脚本中的任何命令以非零状态退出时立即退出。
以下是如何在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 pipefail`。
数据结构
网络
关系数据库管理系统 (RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP