作者 | Vivek Gite
譯者 | zjon
來自我的郵箱:
我寫了一個 hello world 小指令碼。我如何能除錯執行在 Linux 或者類 UNIX 的系統上的 bash shell 指令碼呢?
這是 Linux / Unix 系統管理員或新使用者最常問的問題。shell 指令碼除錯可能是一項繁瑣的工作(不容易閱讀)。除錯 shell 指令碼有多種方法。
您需要傳遞 -x
或 -v
引數,以在 bash shell 中瀏覽每行程式碼。
如何在 Linux 或者 UNIX 下除錯 Bash Shell 指令碼
讓我們看看如何使用各種方法除錯 Linux 和 UNIX 上執行的指令碼。
-x 選項來除錯指令碼
用 -x
選項來執行指令碼:
$ bash -x script-name
$ bash -x domains.sh
使用 set 內建命令
bash shell 提供除錯選項,可以開啟或關閉使用 set 命令[1]:
set -x
: 顯示命令及其執行時的引數。set -v
: 顯示 shell 輸入行作為它們讀取的可以在 shell 指令碼本身中使用上面的兩個命令:
#!/bin/bash
clear
# turn on debug mode
set -x
for f in *
do
file $f
done
# turn OFF debug mode
set +x
ls
# more commands
你可以代替 標準釋伴[2] 行:
#!/bin/bash
用以下程式碼(用於除錯):
#!/bin/bash -xv
使用智慧除錯功能
首先新增一個叫做 _DEBUG
的特殊變數。當你需要除錯指令碼的時候,設定 _DEBUG
為 on
:
_DEBUG="on"
在指令碼的開頭放置以下函式:
function DEBUG()
{
[ "$_DEBUG" == "on" ] && $@
}
現在,只要你需要除錯,只需使用 DEBUG
函式如下:
DEBUG echo "File is $filename"
或者:
DEBUG set -x
Cmd1
Cmd2
DEBUG set +x
當除錯完(在移動你的指令碼到生產環境之前)設定 _DEBUG
為 off
。不需要刪除除錯行。
_DEBUG="off" # 設定為非 'on' 的任何字元
示例指令碼:
#!/bin/bash
_DEBUG="on"
function DEBUG()
{
[ "$_DEBUG" == "on" ] && $@
}
DEBUG echo 'Reading files'
for i in *
do
grep 'something' $i > /dev/null
[ $? -eq 0 ] && echo "Found in $i file"
done
DEBUG set -x
a=2
b=3
c=$(( $a + $b ))
DEBUG set +x
echo "$a + $b = $c"
儲存並關閉檔案。執行指令碼如下:
$ ./script.sh
輸出:
Reading files
Found in xyz.txt file
+ a=2
+ b=3
+ c=5
+ DEBUG set +x
+ '[' on == on ']'
+ set +x
2 + 3 = 5
現在設定 _DEBUG
為 off
(你需要編輯該檔案):
_DEBUG="off"
執行指令碼:
$ ./script.sh
輸出:
Found in xyz.txt file
2 + 3 = 5
以上是一個簡單但非常有效的技術。還可以嘗試使用 DEBUG
作為別名而不是函式。
除錯 Bash Shell 的常見錯誤
Bash 或者 sh 或者 ksh 在螢幕上給出各種錯誤資訊,在很多情況下,錯誤資訊可能不提供詳細的資訊。
跳過在檔案上應用執行許可權
當你 編寫你的第一個 hello world 指令碼[3],您可能會得到一個錯誤,如下所示:
bash: ./hello.sh: Permission denied
設定許可權使用 chmod
命令:
$ chmod +x hello.sh
$ ./hello.sh
$ bash hello.sh
檔案結束時發生意外的錯誤
如果您收到檔案結束意外錯誤訊息,請開啟指令碼檔案,並確保它有開啟和關閉引號。在這個例子中,echo
陳述句有一個開頭引號,但沒有結束引號:
#!/bin/bash
...
....
echo 'Error: File not found
^^^^^^^
missing quote
還要確保你檢查缺少的括號和大括號 {}
:
#!/bin/bash
.....
[ ! -d $DIRNAME ] && { echo "Error: Chroot dir not found"; exit 1;
^^^^^^^^^^^^^
missing brace }
...
丟失像 fi,esac,;; 等關鍵字。
如果你缺少了結尾的關鍵字,如 fi
或 ;;
你會得到一個錯誤,如 “XXX 意外”。因此,確保所有巢狀的 if
和 case
陳述句以適當的關鍵字結束。有關語法要求的頁面。在本例中,缺少 fi
:
#!/bin/bash
echo "Starting..."
....
if [ $1 -eq 10 ]
then
if [ $2 -eq 100 ]
then
echo "Do something"
fi
for f in $files
do
echo $f
done
# 註意 fi 丟失了
在 Windows 或 UNIX 框中移動或編輯 shell 指令碼
不要在 Linux 上建立指令碼並移動到 Windows。另一個問題是編輯 Windows 10上的 shell 指令碼並將其移動到 UNIX 伺服器上。這將由於換行符不同而導致命令沒有發現的錯誤。你可以使用下列命令 將 DOS 換行轉換為 CR-LF 的Unix/Linux 格式[4] :
dos2unix my-script.sh
技巧
技巧 1 - 傳送除錯資訊輸出到標準錯誤
[標準錯誤] 是預設錯誤輸出裝置,用於寫所有系統錯誤資訊。因此,將訊息傳送到預設的錯誤裝置是個好主意:
# 寫錯誤到標準輸出
echo "Error: $1 file not found"
#
# 寫錯誤到標準錯誤(註意 1>&2 在 echo 命令末尾)
#
echo "Error: $1 file not found" 1>&2
技巧 2 - 在使用 vim 文字編輯器時,開啟語法高亮
大多數現代文字編輯器允許設定語法高亮選項。這對於檢測語法和防止常見錯誤如開啟或關閉引號非常有用。你可以在不同的顏色中看到。這個特性簡化了 shell 指令碼結構中的編寫,語法錯誤在視覺上截然不同。高亮不影響文字本身的意義,它只為你提示而已。在這個例子中,我的指令碼使用了 vim 語法高亮:
!如何除錯 Bash Shell 指令碼,在 Linux 或者 UNIX 使用 Vim 語法高亮特性[5]]7[5]
技巧 3 - 使用 shellcheck 檢查指令碼
shellcheck 是一個用於靜態分析 shell 指令碼的工具[6]。可以使用它來查詢 shell 指令碼中的錯誤。這是用 Haskell 編寫的。您可以使用這個工具找到警告和建議。你可以看看如何在 Linux 或 類UNIX 系統上安裝和使用 shellcheck 來改善你的 shell 指令碼,避免錯誤和高效。
作者:Vivek Gite
作者是 nixCraft 創造者,一個經驗豐富的系統管理員和一個練習 Linux 作業系統/ UNIX shell 指令碼的教練。他曾與全球客戶和各種行業,包括 IT,教育,國防和空間研究,以及非營利部門。關註他的 推特[7],臉譜網[8],谷歌+ [9]。
via: https://www.cyberciti.biz/tips/debugging-shell-script.html
作者:Vivek Gite[11] 譯者:zjon 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出