国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
shell調(diào)試技術(shù)
shell調(diào)試技術(shù)

2007 年 7 月 26 日

本文全面系統(tǒng)地介紹了shell腳本調(diào)試技術(shù),包括使用echo, tee, trap等命令輸出關(guān)鍵信息,跟蹤變量的值,在腳本中植入調(diào)試鉤子,使用“-n”選項(xiàng)進(jìn)行shell腳本的語(yǔ)法檢查,使用“-x”選項(xiàng)實(shí)現(xiàn)shell腳本逐條語(yǔ)句的跟蹤,巧妙地利用shell的內(nèi)置變量增強(qiáng)“-x”選項(xiàng)的輸出信息等。

一. 前言

shell編程在unix/linux世界中使用得非常廣泛,熟練掌握shell編程也是成為一名優(yōu)秀的unix/linux開發(fā)者和系統(tǒng)管理員的必經(jīng)之路。腳本調(diào)試的主要工作就是發(fā)現(xiàn)引發(fā)腳本錯(cuò)誤的原因以及在腳本源代碼中定位發(fā)生錯(cuò)誤的行,常用的手段包括分析輸出的錯(cuò)誤信息,通過(guò)在腳本中加入調(diào)試語(yǔ)句,輸出調(diào)試信息來(lái)輔助診斷錯(cuò)誤,利用調(diào)試工具等。但與其它高級(jí)語(yǔ)言相比,shell解釋器缺乏相應(yīng)的調(diào)試機(jī)制和調(diào)試工具的支持,其輸出的錯(cuò)誤信息又往往很不明確,初學(xué)者在調(diào)試腳本時(shí),除了知道用echo語(yǔ)句輸出一些信息外,別無(wú)它法,而僅僅依賴于大量的加入echo語(yǔ)句來(lái)診斷錯(cuò)誤,確實(shí)令人不勝其繁,故常見初學(xué)者抱怨shell腳本太難調(diào)試了。本文將系統(tǒng)地介紹一些重要的shell腳本調(diào)試技術(shù),希望能對(duì)shell的初學(xué)者有所裨益。

本文的目標(biāo)讀者是unix/linux環(huán)境下的開發(fā)人員,測(cè)試人員和系統(tǒng)管理員,要求讀者具有基本的shell編程知識(shí)。本文所使用范例在Bash3.1 +Redhat Enterprise Server 4.0下測(cè)試通過(guò),但所述調(diào)試技巧應(yīng)也同樣適用于其它shell。

二. 在shell腳本中輸出調(diào)試信息

通過(guò)在程序中加入調(diào)試語(yǔ)句把一些關(guān)鍵地方或出錯(cuò)的地方的相關(guān)信息顯示出來(lái)是最常見的調(diào)試手段。Shell程序員通常使用echo(ksh程序員常使用 print)語(yǔ)句輸出信息,但僅僅依賴echo語(yǔ)句的輸出跟蹤信息很麻煩,調(diào)試階段在腳本中加入的大量的echo語(yǔ)句在產(chǎn)品交付時(shí)還得再費(fèi)力一一刪除。針對(duì)這個(gè)問(wèn)題,本節(jié)主要介紹一些如何方便有效的輸出調(diào)試信息的方法。

1. 使用trap命令

trap命令用于捕獲指定的信號(hào)并執(zhí)行預(yù)定義的命令。
其基本的語(yǔ)法是:
trap 'command' signal
其中signal是要捕獲的信號(hào),command是捕獲到指定的信號(hào)之后,所要執(zhí)行的命令??梢杂胟ill –l命令看到系統(tǒng)中全部可用的信號(hào)名,捕獲信號(hào)后所執(zhí)行的命令可以是任何一條或多條合法的shell語(yǔ)句,也可以是一個(gè)函數(shù)名。
shell腳本在執(zhí)行時(shí),會(huì)產(chǎn)生三個(gè)所謂的“偽信號(hào)”,(之所以稱之為“偽信號(hào)”是因?yàn)檫@三個(gè)信號(hào)是由shell產(chǎn)生的,而其它的信號(hào)是由操作系統(tǒng)產(chǎn)生的),通過(guò)使用trap命令捕獲這三個(gè)“偽信號(hào)”并輸出相關(guān)信息對(duì)調(diào)試非常有幫助。


表 1. shell偽信號(hào)
信號(hào)名 何時(shí)產(chǎn)生
EXIT 從一個(gè)函數(shù)中退出或整個(gè)腳本執(zhí)行完畢
ERR 當(dāng)一條命令返回非零狀態(tài)時(shí)(代表命令執(zhí)行不成功)
DEBUG 腳本中每一條命令執(zhí)行之前

通過(guò)捕獲EXIT信號(hào),我們可以在shell腳本中止執(zhí)行或從函數(shù)中退出時(shí),輸出某些想要跟蹤的變量的值,并由此來(lái)判斷腳本的執(zhí)行狀態(tài)以及出錯(cuò)原因,其使用方法是:
trap 'command' EXIT 或 trap 'command' 0

通過(guò)捕獲ERR信號(hào),我們可以方便的追蹤執(zhí)行不成功的命令或函數(shù),并輸出相關(guān)的調(diào)試信息,以下是一個(gè)捕獲ERR信號(hào)的示例程序,其中的$LINENO是一個(gè)shell的內(nèi)置變量,代表shell腳本的當(dāng)前行號(hào)。

$ cat -n exp1.sh
1 ERRTRAP()
2 {
3 echo "[LINE:$1] Error: Command or function exited with status $?"
4 }
5 foo()
6 {
7 return 1;
8 }
9 trap 'ERRTRAP $LINENO' ERR
10 abc
11 foo

其輸出結(jié)果如下:

$ sh exp1.sh
exp1.sh: line 10: abc: command not found
[LINE:10] Error: Command or function exited with status 127
[LINE:11] Error: Command or function exited with status 1

在調(diào)試過(guò)程中,為了跟蹤某些變量的值,我們常常需要在shell腳本的許多地方插入相同的echo語(yǔ)句來(lái)打印相關(guān)變量的值,這種做法顯得煩瑣而笨拙。而通過(guò)捕獲DEBUG信號(hào),我們只需要一條trap語(yǔ)句就可以完成對(duì)相關(guān)變量的全程跟蹤。

以下是一個(gè)通過(guò)捕獲DEBUG信號(hào)來(lái)跟蹤變量的示例程序:

$ cat –n exp2.sh
1 #!/bin/bash
2 trap 'echo “before execute line:$LINENO, a=$a,b=$b,c=$c”' DEBUG
3 a=1
4 if [ "$a" -eq 1 ]
5 then
6 b=2
7 else
8 b=1
9 fi
10 c=3
11 echo "end"

其輸出結(jié)果如下:

$ sh exp2.sh
before execute line:3, a=,b=,c=
before execute line:4, a=1,b=,c=
before execute line:6, a=1,b=,c=
before execute line:10, a=1,b=2,c=
before execute line:11, a=1,b=2,c=3
end

從運(yùn)行結(jié)果中可以清晰的看到每執(zhí)行一條命令之后,相關(guān)變量的值的變化。同時(shí),從運(yùn)行結(jié)果中打印出來(lái)的行號(hào)來(lái)分析,可以看到整個(gè)腳本的執(zhí)行軌跡,能夠判斷出哪些條件分支執(zhí)行了,哪些條件分支沒(méi)有執(zhí)行。

2. 使用tee命令

在shell腳本中管道以及輸入輸出重定向使用得非常多,在管道的作用下,一些命令的執(zhí)行結(jié)果直接成為了下一條命令的輸入。如果我們發(fā)現(xiàn)由管道連接起來(lái)的一批命令的執(zhí)行結(jié)果并非如預(yù)期的那樣,就需要逐步檢查各條命令的執(zhí)行結(jié)果來(lái)判斷問(wèn)題出在哪兒,但因?yàn)槭褂昧斯艿?,這些中間結(jié)果并不會(huì)顯示在屏幕上,給調(diào)試帶來(lái)了困難,此時(shí)我們就可以借助于tee命令了。

tee命令會(huì)從標(biāo)準(zhǔn)輸入讀取數(shù)據(jù),將其內(nèi)容輸出到標(biāo)準(zhǔn)輸出設(shè)備,同時(shí)又可將內(nèi)容保存成文件。例如有如下的腳本片段,其作用是獲取本機(jī)的ip地址:

ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1'
| cut -d : -f3 | awk '{print $1}'`
#注意=號(hào)后面的整句是用反引號(hào)(數(shù)字1鍵的左邊那個(gè)鍵)括起來(lái)的。
echo $ipaddr

運(yùn)行這個(gè)腳本,實(shí)際輸出的卻不是本機(jī)的ip地址,而是廣播地址,這時(shí)我們可以借助tee命令,輸出某些中間結(jié)果,將上述腳本片段修改為:

ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1'
| tee temp.txt | cut -d : -f3 | awk '{print $1}'`
echo $ipaddr

之后,將這段腳本再執(zhí)行一遍,然后查看temp.txt文件的內(nèi)容:

$ cat temp.txt
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0

我們可以發(fā)現(xiàn)中間結(jié)果的第二列(列之間以:號(hào)分隔)才包含了IP地址,而在上面的腳本中使用cut命令截取了第三列,故我們只需將腳本中的cut -d : -f3改為cut -d : -f2即可得到正確的結(jié)果。

具體到上述的script例子,我們也許并不需要tee命令的幫助,比如我們可以分段執(zhí)行由管道連接起來(lái)的各條命令并查看各命令的輸出結(jié)果來(lái)診斷錯(cuò)誤,但在一些復(fù)雜的shell腳本中,這些由管道連接起來(lái)的命令可能又依賴于腳本中定義的一些其它變量,這時(shí)我們想要在提示符下來(lái)分段運(yùn)行各條命令就會(huì)非常麻煩了,簡(jiǎn)單地在管道之間插入一條tee命令來(lái)查看中間結(jié)果會(huì)更方便一些。

3. 使用"調(diào)試鉤子"

在C語(yǔ)言程序中,我們經(jīng)常使用DEBUG宏來(lái)控制是否要輸出調(diào)試信息,在shell腳本中我們同樣可以使用這樣的機(jī)制,如下列代碼所示:

if [ “$DEBUG” = “true” ]; then
echo “debugging” #此處可以輸出調(diào)試信息
fi

這樣的代碼塊通常稱之為“調(diào)試鉤子”或 “調(diào)試塊”。在調(diào)試鉤子內(nèi)部可以輸出任何您想輸出的調(diào)試信息,使用調(diào)試鉤子的好處是它是可以通過(guò)DEBUG變量來(lái)控制的,在腳本的開發(fā)調(diào)試階段,可以先執(zhí)行export DEBUG=true命令打開調(diào)試鉤子,使其輸出調(diào)試信息,而在把腳本交付使用時(shí),也無(wú)需再費(fèi)事把腳本中的調(diào)試語(yǔ)句一一刪除。

如果在每一處需要輸出調(diào)試信息的地方均使用if語(yǔ)句來(lái)判斷DEBUG變量的值,還是顯得比較繁瑣,通過(guò)定義一個(gè)DEBUG函數(shù)可以使植入調(diào)試鉤子的過(guò)程更簡(jiǎn)潔方便,如下面代碼所示:

$ cat –n exp3.sh
1 DEBUG()
2 {
3 if [ "$DEBUG" = "true" ]; then
4 $@  
5 fi
6 }
7 a=1
8 DEBUG echo "a=$a"
9 if [ "$a" -eq 1 ]
10 then
11 b=2
12 else
13 b=1
14 fi
15 DEBUG echo "b=$b"
16 c=3
17 DEBUG echo "c=$c"

在上面所示的DEBUG函數(shù)中,會(huì)執(zhí)行任何傳給它的命令,并且這個(gè)執(zhí)行過(guò)程是可以通過(guò)DEBUG變量的值來(lái)控制的,我們可以把所有跟調(diào)試有關(guān)的命令都作為DEBUG函數(shù)的參數(shù)來(lái)調(diào)用,非常的方便。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
【轉(zhuǎn)】Shell腳本調(diào)試技術(shù)
freebsd-Makefile
shell 腳本中的符號(hào)條件小結(jié)
shell中的點(diǎn)命令與source命令的區(qū)別
Shell編程
Linux中編寫Shell腳本
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服