在任何命令上中止一个shell脚本都会失败

在任何命令上中止一个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 pipeline fail。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程