shell脚本——调试(-n / -x /-c)
我們在前面介紹的調試手段是通過修改shell腳本的源代碼,從其輸出相關的調試信息來定位錯誤的,那有沒有不修改源代碼來調試shell腳本的方法呢?有的,那就是使用shell的執行選項,下面將介紹一些常用選項的用法: -n 只讀取shell腳本,但不實際執行 "-n"可用于測試shell腳本是否存在語法錯誤,但不會實際執行命令。在shell腳本編寫完成之后,實際執行之前,首先使用"-n"選項來測試腳本是否存在語法錯誤是一個很好的習慣。因為某些shell腳本在執行時會對系統環境產生影響,比如生成或移動文件等,如果在實際執行才發現語法錯誤,您不得不手工做一些系統環境的恢復工作才能繼續測試這個腳本。 "-c"選項使shell解釋器從一個字符串中而不是從一個文件中讀取并執行shell命令。當需要臨時測試一小段腳本的執行結果時,可以使用這個選項,如下所示: "-x"選項可用來跟蹤腳本的執行,是調試shell腳本的強有力工具。"-x"選項使shell在執行腳本的過程中把它實際執行的每一個命令行顯示出來,并且在行首顯示一個"+"號。 "+"號后面顯示的是經過了變量替換之后的命令行的內容,有助于分析實際執行的是什么命令。 "-x"選項使用起來簡單方便,可以輕松對付大多數的shell調試任務,應把其當作首選的調試手段。 如果把本文前面所述的trap ‘command’ DEBUG機制與“-x”選項結合起來,我們就可以既輸出實際執行的每一條命令,又逐行跟蹤相關變量的值,對調試相當有幫助。 我們以debug.sh腳本為例: # cat -n debug.sh?? 1 #!/bin/sh2 trap 'echo "before execute line:$LINENO,a=$a,b=$b,c=$c"' DEBUG3 a=14 if [ "$a" -eq 1 ]5 then 6 b=27 else 8 b=19 fi10 c=311 echo end現在對該腳本加上“-x”選項來執行它: 在上面的結果中,前面有“+”號的行是shell腳本實際執行的命令,前面有“++”號的行是執行trap機制中指定的命令,其它的行則是輸出信息。 shell的執行選項除了可以在啟動shell時指定外,亦可在腳本中用set命令來指定。 "set -?參數"表示啟用某選項,"set +參數"表示關閉某選項。有時候我們并不需要在啟動時用"-x"選項來跟蹤所有的命令行,這時我們可以在腳本中使用set命令,如以下腳本片段所示: set -x#啟動"-x"選項 set命令同樣可以使用前面介紹的調試鉤子—DEBUG函數來調用,下面是DEBUG函數代碼:
DEBUG set -x#啟動"-x"選項 DEBUG set +x#關閉"-x"選項 四. 對"-x"選項的增強 "-x"執行選項是目前最常用的跟蹤和調試shell腳本的手段,但其輸出的調試信息僅限于進行變量替換之后的每一條實際執行的命令以及行首的一個"+" 號提示符,居然連行號這樣的重要信息都沒有,對于復雜的shell腳本的調試來說,還是非常的不方便。幸運的是,我們可以巧妙地利用shell內置的一些環境變量來增強"-x"選項的輸出信息,下面先介紹幾個shell內置的環境變量: $LINENO $FUNCNAME $PS4 利用$PS4這一特性,通過使用一些內置變量來重定義$PS4的值,我們就可以增強"-x"選項的輸出信息。例如先執行export PS4='+{$LINENO:${FUNCNAME[0]}} ', 然后再使用“-x”選項來執行腳本,就能在每一條實際執行的命令前面顯示其行號以及所屬的函數名。 以下是一個存在bug的shell腳本的示例,本文將用此腳本來示范如何用“-n”以及增強的“-x”執行選項來調試shell腳本。這個腳本中定義了一個函數isRoot(),用于判斷當前用戶是不是root用戶,如果不是,則中止腳本的執行。 # cat -n debugOthO.sh 首先執行# sh -n debugOthO.sh來進行語法檢查,輸出如下: 發現了一個語法錯誤,通過仔細檢查第6行前后的命令,我們發現是第4行的if語句缺少then關鍵字引起的(寫慣了C程序的人很容易犯這個錯誤)。我們可以把第4行修改為if [ "$UID" -ne 0 ]; then來修正這個錯誤。再次運行# sh -n debugOthO.sh來進行語法檢查,沒有再報告錯誤。接下來就可以實際執行這個腳本了,執行結果如下: # sh -n debugOthO.sh 盡管腳本沒有語法錯誤了,在執行時卻又報告了錯誤。錯誤信息還非常奇怪“[1: command not found”。現在我們可以試試定制$PS4的值,并使用“-x”選項來跟蹤: $ export PS4='+{$LINENO:${FUNCNAME[0]}} ' 從輸出結果中,我們可以看到腳本實際被執行的語句,該語句的行號以及所屬的函數名也被打印出來,從中可以清楚的分析出腳本的執行軌跡以及所調用的函數的內部執行情況。由于執行時是第11行報錯,這是一個if語句,我們對比分析一下同為if語句的第4行的跟蹤結果: +{4:isRoot} '[' 503 -ne 0 ']' 到這里我們就知道由于第11行的[號后面缺少了一個空格,導致[號與緊挨它的變量$?的值1被shell解釋器看作了一個整體,并試著把這個整體視為一個命令來執行,故有“[1: command not found”這樣的錯誤提示。只需在[號后面插入一個空格就一切正常了。 shell中還有其它一些對調試有幫助的內置變量,比如在Bash Shell中還有BASH_SOURCE, BASH_SUBSHELL等一批對調試有幫助的內置變量,您可以通過man sh或man bash來查看,然后根據您的調試目的,使用這些內置變量來定制$PS4,從而達到增強“-x”選項的輸出信息的目的。 五. 總結 現在讓我們來總結一下調試shell腳本的過程: |
參考鏈接:
http://www.360doc.com/content/17/0706/19/33093582_669392362.shtml
總結
以上是生活随笔為你收集整理的shell脚本——调试(-n / -x /-c)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Openldap配置TLS加密传输(完整
- 下一篇: shell脚本——系统变量 与 变量(