Shell 調(diào)試

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

通過(guò)在程序中加入調(diào)試語(yǔ)句把一些關(guān)鍵地方或出錯(cuò)的地方的相關(guān)信息顯示出來(lái)是最常見(jiàn)的調(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í)行的命令表谊。可以用kill –l命令看到系統(tǒng)中全部可用的信號(hào)名盖喷,捕獲信號(hào)后所執(zhí)行的命令可以是任何一條或多條合法的shell語(yǔ)句爆办,也可以是一個(gè)函數(shù)名。
shell腳本在執(zhí)行時(shí)课梳,會(huì)產(chǎn)生三個(gè)所謂的“偽信號(hào)”距辆,(之所以稱(chēng)之為“偽信號(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

這樣的代碼塊通常稱(chēng)之為“調(diào)試鉤子”或“調(diào)試塊”汞扎。在調(diào)試鉤子內(nèi)部可以輸出任何您想輸出的調(diào)試信息季稳,使用調(diào)試鉤子的好處是它是可以通過(guò)DEBUG變量來(lái)控制的,在腳本的開(kāi)發(fā)調(diào)試階段澈魄,可以先執(zhí)行export DEBUG=true命令打開(kāi)調(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)用,非常的方便。

三. 使用shell的執(zhí)行選項(xiàng)

上一節(jié)所述的調(diào)試手段是通過(guò)修改shell腳本的源代碼杜窄,令其輸出相關(guān)的調(diào)試信息來(lái)定位錯(cuò)誤的肠骆,那有沒(méi)有不修改源代碼來(lái)調(diào)試shell腳本的方法呢?答案就是使用shell的執(zhí)行選項(xiàng)塞耕,本節(jié)將介紹一些常用選項(xiàng)的用法:
-n 只讀取shell腳本蚀腿,但不實(shí)際執(zhí)行
-x 進(jìn)入跟蹤方式,顯示所執(zhí)行的每一條命令
-c "string" 從strings中讀取命令
“-n”可用于測(cè)試shell腳本是否存在語(yǔ)法錯(cuò)誤扫外,但不會(huì)實(shí)際執(zhí)行命令莉钙。在shell腳本編寫(xiě)完成之后,實(shí)際執(zhí)行之前筛谚,首先使用“-n”選項(xiàng)來(lái)測(cè)試腳本是否存在語(yǔ)法錯(cuò)誤是一個(gè)很好的習(xí)慣磁玉。因?yàn)槟承﹕hell腳本在執(zhí)行時(shí)會(huì)對(duì)系統(tǒng)環(huán)境產(chǎn)生影響,比如生成或移動(dòng)文件等驾讲,如果在實(shí)際執(zhí)行才發(fā)現(xiàn)語(yǔ)法錯(cuò)誤蚊伞,您不得不手工做一些系統(tǒng)環(huán)境的恢復(fù)工作才能繼續(xù)測(cè)試這個(gè)腳本。

“-c”選項(xiàng)使shell解釋器從一個(gè)字符串中而不是從一個(gè)文件中讀取并執(zhí)行shell命令吮铭。當(dāng)需要臨時(shí)測(cè)試一小段腳本的執(zhí)行結(jié)果時(shí)时迫,可以使用這個(gè)選項(xiàng),如下所示:
sh -c 'a=1;b=2;let c=$a+$b;echo "c=$c"'

"-x"選項(xiàng)可用來(lái)跟蹤腳本的執(zhí)行沐兵,是調(diào)試shell腳本的強(qiáng)有力工具别垮。“-x”選項(xiàng)使shell在執(zhí)行腳本的過(guò)程中把它實(shí)際執(zhí)行的每一個(gè)命令行顯示出來(lái)扎谎,并且在行首顯示一個(gè)"+"號(hào)碳想。 "+"號(hào)后面顯示的是經(jīng)過(guò)了變量替換之后的命令行的內(nèi)容,有助于分析實(shí)際執(zhí)行的是什么命令毁靶。 “-x”選項(xiàng)使用起來(lái)簡(jiǎn)單方便胧奔,可以輕松對(duì)付大多數(shù)的shell調(diào)試任務(wù),應(yīng)把其當(dāng)作首選的調(diào)試手段。
如果把本文前面所述的trap ‘command’ DEBUG機(jī)制與“-x”選項(xiàng)結(jié)合起來(lái)预吆,我們就可以既輸出實(shí)際執(zhí)行的每一條命令龙填,又逐行跟蹤相關(guān)變量的值,對(duì)調(diào)試相當(dāng)有幫助拐叉。
仍以前面所述的exp2.sh為例岩遗,現(xiàn)在加上“-x”選項(xiàng)來(lái)執(zhí)行它:
$ sh –x exp2.sh
+ trap 'echo "before execute line:$LINENO, a=$a,b=$b,c=$c"' DEBUG
++ echo 'before execute line:3, a=,b=,c='
before execute line:3, a=,b=,c=
+ a=1
++ echo 'before execute line:4, a=1,b=,c='
before execute line:4, a=1,b=,c=
+ '[' 1 -eq 1 ']'
++ echo 'before execute line:6, a=1,b=,c='
before execute line:6, a=1,b=,c=
+ b=2
++ echo 'before execute line:10, a=1,b=2,c='
before execute line:10, a=1,b=2,c=
+ c=3
++ echo 'before execute line:11, a=1,b=2,c=3'
before execute line:11, a=1,b=2,c=3
+ echo end
end

在上面的結(jié)果中,前面有“+”號(hào)的行是shell腳本實(shí)際執(zhí)行的命令凤瘦,前面有“++”號(hào)的行是執(zhí)行trap機(jī)制中指定的命令宿礁,其它的行則是輸出信息。

shell的執(zhí)行選項(xiàng)除了可以在啟動(dòng)shell時(shí)指定外蔬芥,亦可在腳本中用set命令來(lái)指定梆靖。 "set -參數(shù)"表示啟用某選項(xiàng)控汉,"set +參數(shù)"表示關(guān)閉某選項(xiàng)。有時(shí)候我們并不需要在啟動(dòng)時(shí)用"-x"選項(xiàng)來(lái)跟蹤所有的命令行返吻,這時(shí)我們可以在腳本中使用set命令姑子,如以下腳本片段所示:

set -x    #啟動(dòng)"-x"選項(xiàng) 
要跟蹤的程序段 
set +x     #關(guān)閉"-x"選項(xiàng)

set命令同樣可以使用上一節(jié)中介紹的調(diào)試鉤子—DEBUG函數(shù)來(lái)調(diào)用,這樣可以避免腳本交付使用時(shí)刪除這些調(diào)試語(yǔ)句的麻煩测僵,如以下腳本片段所示:

DEBUG set -x    #啟動(dòng)"-x"選項(xiàng) 
要跟蹤的程序段 
DEBUG set +x    #關(guān)閉"-x"選項(xiàng)

四. 對(duì)"-x"選項(xiàng)的增強(qiáng)

"-x"執(zhí)行選項(xiàng)是目前最常用的跟蹤和調(diào)試shell腳本的手段街佑,但其輸出的調(diào)試信息僅限于進(jìn)行變量替換之后的每一條實(shí)際執(zhí)行的命令以及行首的一個(gè)"+"號(hào)提示符,居然連行號(hào)這樣的重要信息都沒(méi)有恨课,對(duì)于復(fù)雜的shell腳本的調(diào)試來(lái)說(shuō)舆乔,還是非常的不方便岳服。幸運(yùn)的是剂公,我們可以巧妙地利用shell內(nèi)置的一些環(huán)境變量來(lái)增強(qiáng)"-x"選項(xiàng)的輸出信息,下面先介紹幾個(gè)shell內(nèi)置的環(huán)境變量:

$LINENO
代表shell腳本的當(dāng)前行號(hào)吊宋,類(lèi)似于C語(yǔ)言中的內(nèi)置宏LINE
$FUNCNAME
函數(shù)的名字纲辽,類(lèi)似于C語(yǔ)言中的內(nèi)置宏func,但宏func只能代表當(dāng)前所在的函數(shù)名,而$FUNCNAME的功能更強(qiáng)大璃搜,它是一個(gè)數(shù)組變量拖吼,其中包含了整個(gè)調(diào)用鏈上所有的函數(shù)的名字,故變量${FUNCNAME[0]}代表shell腳本當(dāng)前正在執(zhí)行的函數(shù)的名字这吻,而變量${FUNCNAME[1]}則代表調(diào)用函數(shù)${FUNCNAME[0]}的函數(shù)的名字吊档,余者可以依此類(lèi)推。
$PS4
主提示符變量$PS1和第二級(jí)提示符變量$PS2比較常見(jiàn)唾糯,但很少有人注意到第四級(jí)提示符變量$PS4的作用怠硼。我們知道使用“-x”執(zhí)行選項(xiàng)將會(huì)顯示shell腳本中每一條實(shí)際執(zhí)行過(guò)的命令,而$PS4的值將被顯示在“-x”選項(xiàng)輸出的每一條命令的前面移怯。在Bash Shell中香璃,缺省的$PS4的值是"+"號(hào)。(現(xiàn)在知道為什么使用"-x"選項(xiàng)時(shí)舟误,輸出的命令前面有一個(gè)"+"號(hào)了吧葡秒?)。
利用$PS4這一特性嵌溢,通過(guò)使用一些內(nèi)置變量來(lái)重定義$PS4的值眯牧,我們就可以增強(qiáng)"-x"選項(xiàng)的輸出信息。例如先執(zhí)行export PS4='+{$LINENO:${FUNCNAME[0]}} ', 然后再使用“-x”選項(xiàng)來(lái)執(zhí)行腳本赖草,就能在每一條實(shí)際執(zhí)行的命令前面顯示其行號(hào)以及所屬的函數(shù)名学少。
以下是一個(gè)存在bug的shell腳本的示例,本文將用此腳本來(lái)示范如何用“-n”以及增強(qiáng)的“-x”執(zhí)行選項(xiàng)來(lái)調(diào)試shell腳本疚顷。這個(gè)腳本中定義了一個(gè)函數(shù)isRoot(),用于判斷當(dāng)前用戶是不是root用戶旱易,如果不是禁偎,則中止腳本的執(zhí)行
$ cat –n exp4.sh
     1  #!/bin/bash
     2  isRoot()
     3  {
     4          if [ "$UID" -ne 0 ]
     5                  return 1
     6          else
     7                  return 0
     8          fi
     9  }
    10  isRoot
    11  if ["$?" -ne 0 ]
    12  then
    13          echo "Must be root to run this script"
    14          exit 1
    15  else
    16          echo "welcome root user"
    17          #do something
    18  fi
首先執(zhí)行sh –n exp4.sh來(lái)進(jìn)行語(yǔ)法檢查,輸出如下:
$ sh –n exp4.sh
exp4.sh: line 6: syntax error near unexpected token `else'
exp4.sh: line 6: `      else'

發(fā)現(xiàn)了一個(gè)語(yǔ)法錯(cuò)誤阀坏,通過(guò)仔細(xì)檢查第6行前后的命令如暖,我們發(fā)現(xiàn)是第4行的if語(yǔ)句缺少then關(guān)鍵字引起的(寫(xiě)慣了C程序的人很容易犯這個(gè)錯(cuò)誤)。我們可以把第4行修改為if [ "$UID" -ne 0 ]; then來(lái)修正這個(gè)錯(cuò)誤忌堂。再次運(yùn)行sh –n exp4.sh來(lái)進(jìn)行語(yǔ)法檢查盒至,沒(méi)有再報(bào)告錯(cuò)誤。接下來(lái)就可以實(shí)際執(zhí)行這個(gè)腳本了士修,執(zhí)行結(jié)果如下:

$ sh exp4.sh
exp2.sh: line 11: [1: command not found
welcome root user

盡管腳本沒(méi)有語(yǔ)法錯(cuò)誤了枷遂,在執(zhí)行時(shí)卻又報(bào)告了錯(cuò)誤。錯(cuò)誤信息還非常奇怪“[1: command not found”∑宄埃現(xiàn)在我們可以試試定制$PS4的值酒唉,并使用“-x”選項(xiàng)來(lái)跟蹤:

$ export PS4='+{$LINENO:${FUNCNAME[0]}} '
$ sh –x exp4.sh
+{10:} isRoot
+{4:isRoot} '[' 503 -ne 0 ']'
+{5:isRoot} return 1
+{11:} '[1' -ne 0 ']'
exp4.sh: line 11: [1: command not found
+{16:} echo 'welcome root user'
welcome root user

從輸出結(jié)果中,我們可以看到腳本實(shí)際被執(zhí)行的語(yǔ)句沸移,該語(yǔ)句的行號(hào)以及所屬的函數(shù)名也被打印出來(lái)痪伦,從中可以清楚的分析出腳本的執(zhí)行軌跡以及所調(diào)用的函數(shù)的內(nèi)部執(zhí)行情況。由于執(zhí)行時(shí)是第11行報(bào)錯(cuò)雹锣,這是一個(gè)if語(yǔ)句网沾,我們對(duì)比分析一下同為if語(yǔ)句的第4行的跟蹤結(jié)果:

+{4:isRoot} '[' 503 -ne 0 ']'
+{11:} '[1' -ne 0 ']'

可知由于第11行的[號(hào)后面缺少了一個(gè)空格,導(dǎo)致[號(hào)與緊挨它的變量$?的值1被shell解釋器看作了一個(gè)整體蕊爵,并試著把這個(gè)整體視為一個(gè)命令來(lái)執(zhí)行辉哥,故有“[1: command not found”這樣的錯(cuò)誤提示。只需在[號(hào)后面插入一個(gè)空格就一切正常了攒射。

shell中還有其它一些對(duì)調(diào)試有幫助的內(nèi)置變量醋旦,比如在Bash Shell中還有BASH_SOURCE, BASH_SUBSHELL等一批對(duì)調(diào)試有幫助的內(nèi)置變量,您可以通過(guò)man sh或man bash來(lái)查看匆篓,然后根據(jù)您的調(diào)試目的,使用這些內(nèi)置變量來(lái)定制$PS4浑度,從而達(dá)到增強(qiáng)“-x”選項(xiàng)的輸出信息的目的。

五. 總結(jié)

現(xiàn)在讓我們來(lái)總結(jié)一下調(diào)試shell腳本的過(guò)程:

首先使用“-n”選項(xiàng)檢查語(yǔ)法錯(cuò)誤鸦概,然后使用“-x”選項(xiàng)跟蹤腳本的執(zhí)行箩张,使用“-x”選項(xiàng)之前,別忘了先定制PS4變量的值來(lái)增強(qiáng)“-x”選項(xiàng)的輸出信息窗市,至少應(yīng)該令其輸出行號(hào)信息(先執(zhí)行export PS4='+[$LINENO]'先慷,更一勞永逸的辦法是將這條語(yǔ)句加到您用戶主目錄的.bash_profile文件中去),這將使你的調(diào)試之旅更輕松咨察。也可以利用trap,調(diào)試鉤子等手段輸出關(guān)鍵調(diào)試信息论熙,快速縮小排查錯(cuò)誤的范圍,并在腳本中使用“set -x”及“set +x”對(duì)某些代碼塊進(jìn)行重點(diǎn)跟蹤摄狱。這樣多種手段齊下脓诡,相信您已經(jīng)可以比較輕松地抓出您的shell腳本中的臭蟲(chóng)了无午。如果您的腳本足夠復(fù)雜,還需要更強(qiáng)的調(diào)試能力祝谚,可以使用shell調(diào)試器bashdb宪迟,這是一個(gè)類(lèi)似于GDB的調(diào)試工具,可以完成對(duì)shell腳本的斷點(diǎn)設(shè)置交惯,單步執(zhí)行滥壕,變量觀察等許多功能烟勋,使用bashdb對(duì)閱讀和理解復(fù)雜的shell腳本也會(huì)大有裨益桐智。關(guān)于bashdb的安裝和使用蹦玫,不屬于本文范圍,您可參閱http://bashdb.sourceforge.NET/上的文檔并下載試用只锻。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玖像,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子炬藤,更是在濱河造成了極大的恐慌御铃,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沈矿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡咬腋,警方通過(guò)查閱死者的電腦和手機(jī)羹膳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)根竿,“玉大人陵像,你說(shuō)我怎么就攤上這事】芸牵” “怎么了醒颖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)壳炎。 經(jīng)常有香客問(wèn)我泞歉,道長(zhǎng),這世上最難降的妖魔是什么匿辩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任腰耙,我火速辦了婚禮,結(jié)果婚禮上铲球,老公的妹妹穿的比我還像新娘挺庞。我一直安慰自己,他們只是感情好稼病,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布选侨。 她就那樣靜靜地躺著掖鱼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪援制。 梳的紋絲不亂的頭發(fā)上锨用,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音隘谣,去河邊找鬼增拥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛寻歧,可吹牛的內(nèi)容都是我干的掌栅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼码泛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼猾封!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起噪珊,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤晌缘,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后痢站,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體磷箕,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年阵难,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岳枷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呜叫,死狀恐怖空繁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情朱庆,我是刑警寧澤盛泡,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站娱颊,受9級(jí)特大地震影響傲诵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜维蒙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一掰吕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颅痊,春花似錦殖熟、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钳榨。三九已至,卻和暖如春纽门,著一層夾襖步出監(jiān)牢的瞬間薛耻,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工赏陵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饼齿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓蝙搔,卻偏偏與公主長(zhǎng)得像缕溉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吃型,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容