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