Bash腳本debug攻略

初學Bash時, 我從未想過去debug Bash腳本, 也從未想過Bash腳本也能debug. 隨著技術的增長, 寫的腳本越來越複雜, 使用echo列印日誌來調試腳本的方式越來越捉襟見肘了. 直到某天
通讀了一遍Bash Reference Manual, 才發現Bash腳本也是可以debug的. 下面就介紹三種debug Bash腳本的方式.

1. debug某個腳本

執行腳本有兩種方式, 一是bash script.sh的方式, 二是./script.sh的方式. 通過第一種方式執行腳本時, 加上-x選項即可debug腳本.
輸出的結果中, 以+開頭的行就是debug輸出的資訊.

$ cat test.sh
#!/bin/bash

echo "Time: $(date)"
echo "User: $USER"
echo "Home: $HOME"

$ bash -x test.sh 
++date
+echo 'Time: Mon 11 Jul 2022 11:29:37 PM CST'
Time: Mon 11 Jul 2022 11:29:37 PM CST
+echo 'User: wbourne '
User: wbourne 
+echo 'Home: /home/wbourne '
Home: /home/wbourne 

2. debug特定腳本

前面說過執行腳本有兩種方式, 那如果是用第二種方式執行腳本如何debug呢? 修改腳本的shabangbash -x即可. 每次執行腳本就會輸出debug資訊.
此方式適合debug某個特定的腳本, 執行腳本時會默認輸出debug資訊; 而上面的第一種方式則適合debug任何腳本.

$ cat test.sh
#!/bin/bash -x

echo "Time: $(date)"
echo "User: $USER"
echo "Home: $HOME"

$ ./test.sh 
++date
+echo 'Time: Mon 11 Jul 2022 11:32:52 PM CST'
Time: Mon 11 Jul 2022 11:32:52 PM CST
+echo 'User: wbourne '
User: wbourne
+echo 'Home: /home/wbourne '
Home: /home/wbourne

請注意: 如果修改腳本的shabang為bash -x, 又以bash script.sh的方式執行腳本, 會發生什麼? 居然沒有輸出debug資訊!!!
設置shabang表示設置一個默認解釋器, 如果沒有指定解釋器才會使用shabang中寫的解釋器. 以bash script.sh的方式執行腳本則指定了解釋器為bash, 所以不會有debug資訊.

$ bash test.sh 
Time: Mon 11 Jul 2022 11:32:12 PM CST
User: wbourne 
Home: /home/wbourne 

3. debug腳本某一部分

如果腳本比較長, 我們之關心其中一部分, 就可以使用Bash內置命令set來debug部分腳本.
set -x表示開啟debug, set +x表示關閉debug

$ cat test.sh
#!/bin/bash

echo "Time: $(date)"
set -x
echo "User: $USER"
set +x
echo "Home: $HOME"

$ ./test.sh 
Time: Mon 11 Jul 2022 11:33:43 PM CST
+echo 'User: wbourne '
User: wbourne 
+set +x
Home: /home/wbourne 

4. PS4

既然是debug, 那肯定要詳細才好. 上述debug只不過是輸出了變數值而已, 是不是可以顯示更多資訊? 當然是可以的, debug資訊的提示符是環境變數PS4, 默認為+, 我們可以更改PS4的值, 使其輸出腳本名, 函數名, 行數等更詳細的資訊. 這個提示符還是綠色的哦!

$ echo $PS4
+

$ export PS4='+\e[01;32m[${BASH_SOURCE}:${FUNCNAME[0]}:${LINENO}]\e[00m'

$ bash -x test.sh 
++[test.sh::3]date
+[test.sh::3]echo 'Time: Mon 11 Jul 2022 11:35:08 PM CST'
Time: Mon 11 Jul 2022 11:35:08 PM CST
+[test.sh::4]echo 'User: wbourne '
User: wbourne 
+[test.sh::5]echo 'Home: /home/wbourne '
Home: /home/wbourne 

5. 參考

Tags: