本系列的前面部厘清晰地闡明了另外兩種 shell 腳本調試模式:詳細模式和文法檢查模式,并用易于了解的例子展示了如何在這些模式下啟用 shell 腳本調試。
<a href="https://linux.cn/article-8028-1.html">如何在 linux 中啟用 shell 腳本的調試模式</a>
<a href="https://linux.cn/article-8045-1.html">如何在 shell 腳本中執行文法檢查調試模式</a>
shell 跟蹤簡單的來說就是跟蹤 shell 腳本中的指令的執行。要打開 shell 跟蹤,請使用 <code>-x</code> 調試選項。
這會讓 shell 在終端上顯示所有執行的指令及其參數。
我們将使用下面的 <code>sys_info.sh</code> shell 腳本,它會簡要地列印出你的系統日期和時間、登入的使用者數和系統的運作時間。不過,腳本中包含我們需要查找和更正的文法錯誤。
<code>#!/bin/bash</code>
<code># script to print brief system info</code>
<code>root_id="0"</code>
<code>date=`date`</code>
<code>no_users=`who | wc -l`</code>
<code>uptime=`uptime`</code>
<code>check_root(){</code>
<code>if [ "$uid" -ne "$root_id" ]; then</code>
<code>echo "you are not allowed to execute this program!"</code>
<code>exit 1;</code>
<code>}</code>
<code>print_sys_info(){</code>
<code>echo "system time : $date"</code>
<code>echo "number of users: $no_users"</code>
<code>echo "system uptime : $uptime</code>
<code>check_root</code>
<code>print_sys_info</code>
<code>exit 0</code>
<code>$ chmod +x sys_info.sh</code>
<code>$ sudo bash -x sys_info.sh</code>

shell 跟蹤 - 顯示腳本中的錯誤
從上面的輸出我們可以觀察到,首先執行指令,然後其輸出做為一個變量的值。
例如,先執行 <code>date</code>,其輸出做為變量 <code>date</code> 的值。
我們可以執行文法檢查來隻顯示其中的文法錯誤,如下所示:
<code>$ sudo bash -n sys_info.sh</code>
腳本中文法檢查
如果我們審視這個 shell 腳本,我們就會發現 <code>if</code> 語句缺少了封閉條件的 <code>fi</code> 關鍵字。是以,讓我們加上它,新的腳本應該看起來像這樣:
<code>#script to print brief system info</code>
<code>fi</code>
再次儲存檔案并以 root 執行,同時做文法檢查:
在 shell 腳本中執行文法檢查
上面的文法檢查操作的結果仍然顯示在腳本的第 21 行還有一個錯誤。是以,我們仍然要糾正一些文法。
我們将在 <code>echo</code> 指令中添加閉合雙引号并儲存檔案。修改過的腳本如下:
<code>echo "system uptime : $uptime"</code>
現在再一次檢查文法。
上面的指令不會産生任何輸出,因為我們的腳本文法上正确。我們也可以再次跟蹤腳本執行,它應該工作得很好:
跟蹤 shell 腳本執行
現在運作腳本。
<code>$ sudo ./sys_info.sh</code>
用 shell 腳本顯示日期、時間和運作時間
<a target="_blank"></a>
shell 腳本跟蹤可以幫助我們識别文法錯誤,更重要的是識别邏輯錯誤。例如,在 <code>sys_info.sh</code> shell 腳本中的 <code>check_root</code> 函數,它用于确定使用者是否為 root,因為腳本隻允許由超級使用者執行。
這裡的魔法是由 <code>if</code> 語句表達式 <code>["$ uid" -ne "$ root_id"]</code> 控制的,一旦我們不使用合适的數字運算符(示例中為 <code>-ne</code>,這意味着不相等),我們最終可能會出一個邏輯錯誤。
假設我們使用 <code>-eq</code> (意思是等于),這将允許任何系統使用者以及 root 使用者運作腳本,是以是一個邏輯錯誤。
<code>if [ "$uid" -eq "$root_id" ]; then</code>
注意:我們在本系列開頭介紹過,<code>set</code> 這個 shell 内置指令可以在 shell 腳本的特定部分激活調試。
是以,下面的行将幫助我們通過跟蹤腳本的執行在其中找到這個邏輯錯誤:
具有邏輯錯誤的腳本:
<code>#turning on and off debugging of check_root function</code>
<code>set -x ; check_root; set +x ;</code>
儲存檔案并調用腳本,在輸出中,我們可以看到一個普通系統使用者可以在未 sudo 的情況下運作腳本。 這是因為 <code>user_id</code> 的值為 100,不等于為 0 的 root 的 <code>root_id</code> 。
<code>$ ./sys_info.sh</code>
run shell script without sudo
原文釋出時間為:2017-01-15
本文來自雲栖社群合作夥伴“linux中國”