本教程(嚴格說起來算不上一個教程)所有實例和方法在HP-UX11.00(L2000)通過。對於其它的 UNIX 平台或SHELL,做相應調整即可。本教程旨在教你如何調試你的Shell程序,不涉及Shell編程的其它知識和技巧。有任何問題請不要hesitate to給我發郵件:
[email protected]
本教程(嚴格說起來算不上一個教程)所有實例和方法在HP-UX11.00(L2000)通過。對於其它的
UNIX平台或SHELL,做相應調整即可。本教程旨在教你如何調試你的Shell程序,不涉及Shell編程的其它
知識和技巧。有任何問題請不要hesitate to給我發郵件:
[email protected] !
先照著輸入這個小程序,判斷當前的SHELL是不是sh(HP-UX默認的Shell是sh):
#vi getsh.sh
#!/usr/bin/sh
curr_sh=`ps|grep $$|awk ‘{print $4}’`
if [ curr_sh=”sh” ]
echo “The current shell is sh.”
else
echo “The current shell isn’t sh.”
fi
首先我們讓它可執行:
#chmod 755 getsh.sh
第一步,你必須
測試有沒有語法錯誤,而且你也可以立即測試了:
#./getsh.sh
./getsh.sh[3]: syntax error at line 6: ‘else’ unexpected
通過實際運行的系統錯誤提示,你知道了是if語句出問題了。
可是,你不應該這麼做!假如這個shell是和系統有關,比如涉及到修改系統核心參數、涉及到刪除備份文件等,就不能通過這種方式來調試語法了。大部分的Shell都提供一個-n參數,作用是僅僅讀入腳本而不實際運行。比如,你現在想調試getsh.sh,那麼你可以這樣:
#/usr/bin/sh –n ./getsh.sh
./getsh.sh[3]: syntax error at line 6: ‘else’ unexpected
一樣可以得到語法上的錯誤提示,而實際上這些腳本並不運行,是不是
安全極了?如果你希望看到shell讀入的每一行程序,還可以加上一個-v參數,比如:
#/usr/bin/sh –vn ./getsh.sh
#!/usr/bin/sh
curr_sh=`ps|grep $$|awk ‘{print $4}’`
if [ curr_sh=”sh” ]
echo “The current shell is sh.”
else
./getsh.sh[3]: syntax error at line 6: ‘else’ unexpected
可以看出,執行到else的時候就出錯了!好象需要一個then哦……
那好,知道是if ..then…else..fi的問題,我們修改一下程序為:
#!/usr/bin/sh
curr_sh=`ps|grep $$|awk ‘{print $4}’`
if [ curr_sh=”sh” ]
then
echo “The current shell is sh.”
else
echo “The current shell isn’t sh.”
fi
做語法檢查:
#/usr/bin/sh –n ./getsh.sh
通過,耶!!!(當然,實際上可能你的shell程序非常長,調試了好幾個小時或好幾天,終於通過了才“耶”,否則,用這個字說明你太容易滿足了,題外話,嘿嘿)
語法沒問題了,是不是你的腳本就一點問題都沒有了呢?當然不是。
#./getsh.sh
The current shell isn’t sh.
和你預計的結果有出入吧!
#ps|grep $$|awk ‘{print $4}’
sh
既然當前shell確實是sh,那麼問題一定出在if語句上。好,現在就來進行shell的跟蹤調試:
#vi ./getsh.sh
#!/usr/bin/sh
curr_sh=`ps|grep $$|awk ‘{print $4}’`
set -x
if [ curr_sh=”sh” ]
then
echo “The current shell is sh.”
else
echo “The current shell isn’t sh.”
fi
注意程序增加了一行
set –x
這是打開shell跟蹤模式的方法。如果沒有set +x語句出現,那麼腳本將按跟蹤模式運行到結尾。一般都不希望這麼做,而僅僅跟蹤某一段程序。比如:
set –x
【要跟蹤的程序段】
set +x
現在實際運行看看:
#./getsh.sh
+ [curr_sh = sh ]
+ echo The current shell isn’t sh.
The current shell isn’t sh.
這裡,所有+開頭的行都是shell真正執行了的命令,其它行是這些命令的輸出。
看看都執行了什麼?curr_sh=sh,怎麼會出現這個比較啊?……$curr_sh……
於是改程序為:
#!/usr/bin/sh
curr_sh=`ps|grep $$|awk ‘{print $4}’`
if [ $curr_sh=”sh” ]
then
echo “The current shell is sh.”
else
echo “The current shell isn’t sh.”
fi
再來:
#./getsh.sh
The current shell isn’t sh.
怪事!!!再認真確認100遍上面的程序,實在是找不出別的什麼問題了。
還得求助於set –x,於是改程序為:
#!/usr/bin/sh
curr_sh=`ps|grep $$|awk ‘{print $4}’`
set -x
if [ $curr_sh=”sh” ]
then
echo “The current shell is sh.”
else
echo “The current shell isn’t sh.”
fi
#./getsh.sh
+ [ getsh.sh = sh ]
+ echo The current shell isn’t sh.
The current shell isn’t sh.
當前Shell已經不是sh而是腳本文件getsh.sh,難怪!調試完成記得把set –x刪除哦。
至此getsh.sh程序調試完畢,其中做了語法錯誤調試、邏輯錯誤調試和結果測試,算是基本完成了一個Shell要用到的所有調試步驟。對於一些很大的shell程序,可以在要調試的地方加入一個測試語句,比如:
if [ $SHELL_DEBUG = “scriptmus
tde
bug” ]
then
set –x
fi
這樣,要調試的時候,就設置SHELL_DEBUG = “scriptmustdebug”,調試完成,清除SHELL_DEBUG變量值即可,有些教材也把這種方法叫做“調試鉤子“!