1. 程式人生 > >shell開發規範

shell開發規範

及其 維護 每次 出現 put 實現 style 轉載 解釋器

版本1.0版,參考網上的一些文章規整而來。後期打算繼續修改。完成一篇適合自己的shell開發規範。

最新編輯時間:2017.6.25

一、 命名規範

1、 版本和運行參數

1) 腳本開始之前以註釋形式說明版本號;(推薦)
2) 如果調用其他工具,還需說明工具的版本號;(推薦)
3) 為腳本添加必須的運行參數,類似於C程序的運行參數,可使用getopt的方式取得運行參數值,如基本的參數有:-v - 版本號;-h – 幫助信息;(推薦)

2、 變量命名

1) 變量命名要前後統一,建議使用全部大寫字母,如APACHE_ERR_NUM;語義要清晰,能夠正確表達變量的含義,過長的英文單詞可采用前幾個字符代替。多個單詞連接使用“_”號連接, 引用時,必須以${APACHE_ERR_NUM}方式引用;

2) 避免無含義字符或數字: 例如下面的數字22, 並不知道其確切含義.

COUNT=`grep keywords file`
if [ ${COUNT} –ne 22 ]
then
    Do Something
fi

3) 全局變量和局部變量:
i. 如需要使用全局變量,則在變量加前綴g,如g_WORK_DIR,在變量使用時,使用{}將其括起,即${VARIABLE}
ii. 局部變量的使用:腳本在定義在一個函數(function)中的變量我們稱之為局部變量,必須要以local方式進行聲明,使之只在本函數中作用有效,以免造成在函數中的命名與程序中變量重名,造成對程序中正常變量的不正常操作。如

function TestFunc()
{
    local i
    for((i=0;i<n;i++))
    do
        do something
    done
}    

4) 變量合並:當某些變量或配置項要組合起來才有意義時,如文件的路徑和文件名稱,建議將要組合的變量合並到一起賦值給一個新的變量,這樣既方便之後的調用,也為以後進行修改提供了方便。

3、 函數命名

1) 函數命名使用單詞首字母大寫,如CreateFile,並且要語義清晰,如使DumpDataToFile()代替DataFile()。同時要註意前後綴,如後綴為Max則為最大值,Min為最小值,前綴Is為判斷型函數,Get則為取值函數,這樣有益於對函數的返回理解更清晰。

2) 註意在使用單詞縮寫時,也使用首字母大寫,如GetHtmlContent而並非GetHTMLContent,這樣有利於命名規則的統一。

4、 腳本(模塊)命名

1) Shell腳本使用統一後綴:.sh
2) 所有模塊的啟動和停止腳本必須統一命名為start_{模塊名}.sh和stop_{模塊名}.sh
3) 模塊(及其腳本和二進制程序) 命名應該代表其特性和功能,禁止使用個人名字縮寫等形式命名。
4) 模塊中的腳本和二進制程序命名禁止和其他腳本和二進制程序重名。
5、 臨時文件的命名
盡量避免臨時文件,如果一定要使用臨時文件,請使用腳本的pid作為後綴,並在腳本結束時清除臨時文件。例如:

PID=$$
TMP_FILE=”tmp_keywords.”${PID}
grep keywords files > ${TMP_FILE}
.....
#end
rm ${TMP_FILE}

二、 代碼風格

1、 代碼框架

1) 解釋器聲明最好為 #!/bin/sh(推薦),如果不是再加入crontab計劃任務時要格外註意執行環境。
配置文件/庫函數的引用 source foo_conf.sh
2) 主過程只實現程序主幹,功能實現應該封裝在子函數中;
3) 對於能獨立執行的腳本需要有usage和version函數,可以輸出腳本用法和版本信息(推薦)

2、 函數

1) 函數定義時在函數名前加上function保留字
2) 顯示函數返回:在函數的每個分支在函數的每個分支都包含顯示的return語句,並跟上返回值。即使是不關心返回值的函數,也可能在後續調用時無意的去判斷它的返回值並進行一系列動作,這種不必要的麻煩我們在一開始就應該註意,顯示的寫return語句並不會帶來多少負擔,相反的,它能讓函數邏輯更加清晰和嚴謹。

3、 條件語句與循環

1) 在使用條件語句及循環時,盡量使用統一格式,而不是使用“;”分隔;

if [ -d abc ]
then
    Do something
fi

while [ 1 ]
do
    Do something
done

for i in *
do
    Do something
Done

2) 盡量使用每一行一條語句,而不是使用”;”將多個語句隔開。盡可能多的判斷操作是否成功,並對其進行相應處理,如DoSth && DoRight || DoWrong 。這樣使用簡化了語句,也使語義變得更加清晰明了;
3) 要使用簡單的語句。特別是應避免多重管道的命令,多重管道的命令在每次閱讀時都需要關註每條管理的信息,直到最後一個命令,如果將其拆分成多個語句,可讀性強;
4) 承接上面第3)點,腳本中經常有grep cut awk sed等命令一起配合的復雜語句。這時應盡量考慮簡化語句。例如多個grep awk操作經常可以由1個sed替代。

4、 縮進

在使用條件語句時,每進行一層循環或是循環內部的操作,就使用一個縮進,縮進一般用TAB鍵。

if [ -d abc ]
then
cd abc
    if [ -d bcd ]
    then
        DoSth
    fi
cd ..
fi

三、 註釋規範

1、 文件/模塊說明

說明模塊主要用途,版本信息,輸入輸出文件,依賴工具及其版本信息, 前後流程腳本(可選),格式統一即可,不做強制要求,可如下:

##! @TODO: url analyse 
##! @VERSION: 1.0 
##! @AUTHOR: MM;BB 
##! @FILEIN: data/url.crawl
##! 由dedup_crawl.sh生成, 格式為... 
##! @FILEOUT: result/GOOD_GRP
##! 通過檢測的無問題alias組 ##! @FILEOUT: result/WRONG_GRP
##! 未通過檢測的有問題alias組 
##! @DEP: wget 1.10.2 
##! @DEP: lftp 3.0.6 
##! @PREV: dedup_crawl.sh 
##! @NEXT: dedup_update.sh

註釋中的路徑給出的相對路徑都必須是相對於該模塊安裝時生成的根目錄。
example:
模塊seek_url安裝在PATH目錄下,安裝後生成了新的目錄seek_url,那麽所有的相對路徑都是相對於PATH/seek_url/的。

推薦為腳本的配置和在處理流程中位於本腳本之前和之後的腳本寫註釋。以便於測試和新人熟悉模塊流程。 (推薦)

example:
##! @conf conf/config_dedup_check.sh
##! dedup-check的模塊範圍的配置文件
##! 這裏主要讀取BINPATH 和 ALIAS_FILE設置
處理流程中在本腳本之前的腳本名
##! @prev dedup_crawl.sh
處理流程中在本腳本之後的腳本名
##! @next dedup_update.sh

所有腳本都要在腳本或配置文件中寫明:依賴的模塊、工具、腳本 (必須)

example:
##! @dep spuser-ftool
##! 簡要說明
##! @dep read_di
##! 簡要說明

2、 重要函數說明

對於重要函數,需說明函數用途,參數,返回值,作者,版本,格式也不做強制要求,可如下:

##! @TODO: get hostname 
##! @AUTHOR: somebody 
##! @VERSION: 1.0 
##! @IN: $1 => ip 
##! @IN: $2 => port 
##! @OUT: 0 => success; 1 => failure


3、 其它

腳本中一定要有十分詳細的註釋,包括變量的定義,函數的定義,返回值的函義,每步操作的目的等,這方面尤其要加強。註釋盡量使用標準的英文或是詳細的中文說明。

四、 日誌規範

1. 腳本和C程序一樣,需要有日誌記錄腳本的運行狀態,操作過程等。推薦:每條日誌要以記錄的當前時間為開頭,然後是記錄的日誌描述信息,描述信息要包括日誌的級別,如FATAL,WARNING,NOTICE等,還要保留充分完整,無歧義的上下文信息,尤其是FATAL和WARNING日誌更是如此。
2. 每個腳本程序要有自己的日誌文件,不要將多個腳本的日誌記錄到同一個日誌文件中,即使這些腳本之間有依賴關系也不可以。

五、 接口文件規範

1. 所有模塊之間的接口文件必須在生成的同時生成md5校驗碼,並且一個文件對應一個md5文件,md5文件的命名為接口文件名後加上“.md5”。
2. 機器之間的數據拷貝推薦使用wget,盡量減少scp和ssh的使用。但是只要是wget獲取遠程數據,必須使用md5校驗數據的完整性。
3. 推薦所有接口文件都進行格式檢查,對空文件和不存在的文件判斷方式應該一致。
4. 推薦接口文件最好有相應的flag文件指明生成時間,以便檢查和容錯。

六、 配置規範

在多個腳本程序協同工作時,應該盡量使用公共函數庫來完成近似的功能,使用配置文件統一變量及外部數據的引用,這樣便於日後的功能升級及環境的變更操作。如果使用了公共函數庫,建議在配置文件中添加公共函數庫腳本的路徑,即使是在當前目錄下也要進行配置,如FILENAME_PATH=”./”,腳本中的公共函數庫及配置文件使用source ${FILENAME_PATH}/filename.sh方式加載。

1、 配置文件

1) 所有的腳本必須把功能和配置明確分開;
2) 配置文件,以conf_腳本名.sh 來命名(推薦);
3) 原則上,配置項放在目錄conf/底下,引用時通過source conf/conf_spdata.sh的形式加載;
4) 配置項的命名規範與變量命名規範相同,要求所有的配置項應都有值,避免內容為空的配置項出現,配置項的內容由雙引號括起,如:
OUTPUT_FILE_PATH=”./output”
5) 路徑參數的配置:腳本中經常需要配置路徑,本地路徑或者遠程機器的路徑。路徑的配置強烈推薦使用全局路徑,全局路徑的配置建議以“/”開頭,末尾沒有“/”,腳本中使用路徑的配置項時,必須以“/”分隔不同的配置項,變量或通配符等,不可以省略“/”。
6) 易變參數的配置:易變參數中主要是指狀態報告和報警的收件人,都必須寫成配置。
7) 機器名,端口和用戶名引用:所有線上腳本都必須通過配置引用機器名、端口和用戶名等信息。
8) 二進制程序引用:當模塊中需要調用非本模塊維護的二進制程序/腳本時,都必須通過一個可配置的路徑來間接引用,禁止直接復制其它模塊的二進制程序到自身目錄使用。

2、 配置項的檢查

1) 腳本中要檢查配置項是否為空,尤其是一些重要的,影響下面腳本正常運行的配置項,必須要進行是否為空的檢查,避免配置文件中有遺漏等錯誤,檢查格式可如下:

if [ -z ${OUTPUT_FILE_PATH} ]
then
    Do something, such as write log
fi

七、 報警規範

1) 報警郵件的標題(和短信報警)必須為如下格式:
[報警級別] [服務名] [機器名] [模塊名] 報警信息 [時間]
示例:

echo "[error][image][$(hostname -s)][${0}][ urlmerge for group ${group_no} failed ][$(date +‘%Y-%m-%d %H:%M:%S‘)]"


2) 報警郵件的發件人必須真實,報警短信必須包括發件機器名。不容許在A機器上發出以B機器名義的報警,推薦使用 `hostname` 命令

3) 線上模塊報警郵件(或短信)的收件人必須包括模塊負責人,指導人,op,禁止將模塊報警(或短信)發給全組。 每個包含信息相同的報警原則上不得多於3條。(必須)

八、 其它細節

1) 涉及依賴的機器,需以配置的形式出現在腳本的配置文件;禁止在腳本中隨處定義機器,這樣不易於維護,也容易出錯; (必須)
2) 必須要有基本的日誌輸出;(必須)
3) 要關註腳本的效率和系統消耗,綜合、平衡的考慮;(必須)
4) 函數參數傳遞:在調用函數時,向函數傳遞的參數如果是以變量的方式進行傳遞,必須使用雙引號將變量括起,這是為了防止某個變量中含有多個以空格分隔的字段,導致函數誤認為是多個參數,如報警郵件和報警短信的配置項,使用方式如下:

Alert “some thing” “${LOG}” “${ALERT_MAIL}” “${ALERT_MOBILE}”

5) 避免cat 大文件。比如 for id in `cat id_file`;do … ;done。而是采用readline形式讀入文件。(必須)
6) 所有上一級命令需用 if [ $? ] 來判斷返回值,對於異常分支,需有相應的處理策略:或是打印warning日誌,或是報警退出/重試。(必須)
7) Sort超過1G的數據文件時,必須用-T指定其臨時文件夾,推薦在使用到sort的時候就使用-T指定到自身的TMP目錄。(必須)
8) 避免使用大的while/for循環,如果實在需要,請考慮用awk命令替代。(推薦)
9) 需要配置crontab的腳本,要註意crontab的時間可能會有前後1分鐘之內的波動,對於時間精度要求較嚴格的腳本,不建議配置在比如00分鐘這樣的時刻。
10) 對於一系列有嚴格依賴關系的命令,建議使用 && 來處理,比如:make mydir && mv myfile mydir;並且對於有前後次序的腳本,禁止采用後臺運行 & 命令。(推薦)
11) 腳本運行前後,註意清除過期數據(上次運行生成的數據)(推薦)
12) 腳本開始運行之前需明確當前運行路徑,例如cd /home/img/img;同時必須明確數據生成路徑,例如 data/spdata_stat/splendid.list;(必須)
13) 對於功能較為復雜的腳本,考慮使用一些函數對功能點進行封裝。這樣可以使腳本清晰易讀;(推薦)
14) 任何出錯情況必須將出錯信息打印到日誌中;嚴重的錯誤必須以郵件或短信報警的形式發出。(必須)
15) 對於邏輯比較復雜的腳本,可以使用 set -x 來打印命令執行情況,便於調試和排錯 (推薦)
16) wget之前,註意先刪除本地文件;(推薦)
17) 拷貝比較大的文件時,最好先將文件cp到一個臨時文件夾,然後mv到目標文件夾。這樣可以避免下遊模塊讀取到了不完整的文件。(推薦)
18) mv,cp等命令,註意要使用 –r –f等遞歸和強制命令(必須)
19) 腳本中,要註意對單引號‘’雙引號“”的轉義。不明確轉義含義的,最好在單元自測的時候多加小心。(推薦)
20) 使用paste命令的時候,註意分清楚,文件是使用tab還是空格作分隔符。
21) 使用ps axuw|grep來獲取信息時,註意ps打印的最大寬度。建議多打幾個w,例如ps axuwwww|grep … ;(推薦)
22) 使用sort,uniq,join,comm等命令時,要註意兩點:1,是否要求排序(例如uniq,join,comm要求輸入文件是排好序的);2,如果排序,要求以什麽方式排序(例如,comm要求輸入文件是字典序的,而不是數值序);(推薦)
23) 字段匹配日誌的時候,要註意特殊字符,例如

spurl[stargirls]spid[2534969]opusr [stargirls]opuid[6545440]

  這樣的日誌,如果只使用[ 和]作分隔符,就會有問題,因為spurl中就可能含有[或]等特殊字符,從而導致後面的匹配全部出錯。
24) 對特殊信號的處理:在腳本運行時,我們有時會臨時中斷此腳本(ctrl+c),如果腳本在做多個文件操作,並生成一些臨時文件,那麽我們在中斷腳本時,就需要恢復或清除一些過程文件。在復雜腳本中,要對一些中止的信號進行特殊的處理。

參考:

本文地址:http://www.cnblogs.com/chinas/p/7073061.html,轉載請註明出處,謝謝!!!

shell開發規範