shell指令碼心得

dbhelper發表於2014-11-26

零零星星的接觸到寫一些shell也有一些日子了,發現自己已經犯了不少的錯誤,自我總結下。

選擇合適的shell

shell本身有很多種,大體有如下的幾種。

/bin/sh (已經被 /bin/bash 所取代)
/bin/bash (就是 Linux 預設的 shell)
/bin/ksh (Kornshell 由 AT&T Bell lab. 發展出來的,相融於 bash)
/bin/tcsh (整合 C Shell ,提供更多的功能)
/bin/csh (已經被 /bin/tcsh 所取代)
/bin/zsh (基於 ksh 發展出來的,功能更強大的 shell)

可以根據工作的需要和自己的實際情況來選擇,目前我使用比較多的就是bash,ksh

 

不同路徑執行,不會影響結果

這個問題比較糾結,在自己寫的一些指令碼中,沒有注意到一些路徑的設定,可能在當前目錄下執行指令碼和在其他路徑下執行就有很大的差別,甚至是嚴重的錯誤。

比如我現在有一個指令碼test.sh在目錄 /u01/ora11g下面。

那麼我在/u01/ora11g下面執行自然沒有問題,但是比如我現在在/u02/db2的目錄下面,我想執行這個test.sh 可能就需要輸入 ksh /u01/ora11g/test.sh xxxxx

如果路徑的一些通用性沒有考慮到的話,這個指令碼很可能出錯,或者出現不期望的結果。

 

臨時檔案的處理和命名

對於臨時檔案的處理,個人建議統一命名,比如以以下特定的操作,功能命名。

xxxx_rename_file.tmp等等。

 

命令的簡化和功能的簡化

對於這個部分,需要大家自己把握一個度,可能有些人喜歡用一個很“精簡”的命令來完成一個很複雜的工作。有些人喜歡透過一些很簡單的操作來組合起來,完成一個複雜的功能。

但是需要大家自己把握這個度,如果指令碼的維護和後期的改進不是你一個人來完成的話,最好還是以一些規範為主,適當加入一些相關的註釋和說明。有些精簡的命令可以加一些特定的描述,這樣在後期需要改進,就很容易把握。

 

適用的平臺

如果大家在unix,linux下寫過一些指令碼,可能會發現有一些命令的選項在Linux可用,但是到了Unix下卻並不買賬。

比如awk,grep在SunOS,AIX,linux下對應的路徑有很大的差別,如果想讓命令更通用,可以考慮下面的形式。

if [ $MachineType = SunOS ]
then
    export AWK=/usr/xpg4/bin/awk
    export GREP=/usr/xpg4/bin/grep
    export SED=/usr/xpg4/bin/sed
    export TR=/usr/xpg4/bin/tr
    export RM=/usr/xpg4/bin/rm
    export CAT=/usr/bin/cat
    export MV=/usr/xpg4/bin/mv
    export CUT=/usr/bin/cut
    export WHOAMI=/usr/ucb/whoami
    export SORT=/usr/xpg4/bin/sort
    export CP=/usr/xpg4/bin/cp
elif [ $MachineType = AIX ]
then
    export AWK=/usr/bin/awk
    export GREP=/usr/local/bin/grep
    export SED=/usr/bin/sed
    export TR=/usr/bin/tr
    export RM=/usr/bin/rm
    export CAT=/usr/bin/cat
    export MV=/usr/bin/mv
    export CUT=/usr/bin/cut
    export WHOAMI=/usr/bin/whoami
    export SORT=/usr/bin/sort
    export CP=/usr/bin/cp
elif [ $MachineType = Linux ]
then
    export AWK=/bin/awk
    export GREP=/bin/grep
    export SED=/bin/sed
    export TR=/usr/bin/tr
    export RM=/bin/rm
    export CAT=/bin/cat
    export MV=/bin/mv
    export CUT=/bin/cut

。。。。。

日誌

對於指令碼中的資料,檔案處理,最好還是有一些詳盡的日誌,沒有日誌,誰也不知道到底發生了什麼。

而且對於問題的排查時極為重要的。

 

函式庫

如果你已經沉澱了不少的功能集,可以考慮把他們整合到函式庫中,在以後的處理中直接呼叫即可。

 

動態指令碼

完成一些複雜的功能時,可以考慮使用動態指令碼來實現。

可以考慮透過shell指令碼來生成一些特定功能的shell指令碼。

比如:使用動態變數進行動態資料比較

http://blog.itpub.net/23718752/viewspace-1210639/

 

完整的資料校驗和容錯處理

指令碼的編寫過程中,可能大家經常忽略的就是一些資料的校驗功能,可能有很多細節都沒有做校驗,在複雜的場景中就很容易出錯,如果要寫一個比較完善的指令碼,那麼資料的校驗和錯誤的處理都是需要格外關注的,畢竟軟體的很多細節都是成敗的關鍵。

 

強大的工具集 sed+awk

sed+awk在shell指令碼的編寫中有很重要的作用,使用的過程中正規表示式的一些知識也需要補補。

有很多的功能可能透過一些檔案處理能夠實現,但是有時候就很容易使用sed/awk來完成。

拋磚引用一下,比如我想對當前目錄下的檔案,輸出檔名都新增一個字尾.abc 

可以這樣來寫

ls -l|awk ‘{print $9 “.abc”}’

 

互動性

可能在寫指令碼的時候,大家對於一些引數需要輸入,就可以提供一些可讀性的提示資訊。這樣在操作的時候更容易理解。

可以使用read來引入一些輸入引數的值,加入一些提示資訊。

cat test.sh

echo  'please input your message:'; read name
echo 'your message is :'$name

[ora11g@rac1 ~]$ ksh testa.sh
please input your message:
this is a test
your message is :this is a test

 

充分利用其他的工具的功能集

使用shell做資料的運算,和其他程式語言相比,感覺還是比較的吃力,比如我想做一個舍入的運算,在oracle中就是ceil()函式實現的功能。

使用一個簡單的sql就馬上得到期望的結果,。

SQL> select ceil(100/3) from dual;

CEIL(100/3)
-----------
         34

但是使用shell需要類似下面的一些轉換和處理,當然了在檔案的處理方面,shell的功能很強大。

pages_float=`echo "scale=2 ; 100 / 3 "|bc`
pages_num=`echo '' | awk -v a=$pages_float '{print int(a+0.999)}'`

echo $pages_num
34

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-1347066/,如需轉載,請註明出處,否則將追究法律責任。

相關文章