任何命令失敗都會中止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`。

更新於:2023年1月3日

13K+ 瀏覽量

啟動您的職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.