如題,最先接觸shell腳本是大學的時候,感受好複雜,最近幾年工做中也零零散散的接觸過不少,不少都是網上找資源進行解決,這兩天在寫自動部署的初始化腳本,感受仍是挺多不足的。linux
shell腳本寫的有點c語言的感受,是過程語言,可是如何模塊化就很是重要了,首先個人第一個版本是完成了從遠端服務器獲取資源文件,一鍵部署tomcat,jdk,生成backup目錄,log目錄,web目錄,script目錄,tools目錄,生成tomcat自啓動腳本。以及和遠端服務器的交互等。整個shell腳本寫下來花了半天的時間,一個方法搞定所有,沒有錯誤處理機制,沒有合適的操做日誌。全部就有了下面的重構。web
shell腳本中遇到的問題shell
1.執行腳本的日誌打印,錯誤記錄,相似於日誌機制沒有編程
v1.0的版本採用的日誌方式是,直接print,遇到錯誤直接returnapi
v2.0的方式,如今的方式是模塊化日誌方式,看代碼tomcat
#調試,調用wget記錄日誌 debug() { if [ $global_is_debug = "true" ];then debug_str=$1 echo "debug:##### ${debug_str} #####\n" fi } #錯誤,調用wget記錄日誌 error() { echo "error:########### $1 ############\n" }
2.用wget方式和遠程服務器交互,特殊字符處理服務器
v1.0:直接wget –i 一個列表,而後存到本地,一系列操作後,刪除文件模塊化
優勢是,簡單粗暴,缺點是不能適應自動化部署工具
v2.0:封裝wget模塊,經過和遠程服務器交換,動態獲取下載列表,根據須要保存到指定目錄,優勢:更具備擴展性,缺點是,服務器請求多post
在和遠端服務器交換的時候設計到特殊字符及漢子的處理,v2.0封裝了一個urlencode方法,進行轉碼。代碼以下:
#進行編碼,編碼結果放在全局變量裏面 urlEncode() { #須要被編碼的字符串 encode_str_params1=$1 debug "${encode_str_params1}" #編碼 global_encode_str=`echo "${encode_str_params1}" | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g'` return }
補充一點:wget 對於請求的url帶有特殊字符的處理,我後臺採用的是struts2,提供的api接口帶有 例如 http//t.cn/api/linux!errorDebug?xx=oo&oo=xx
你採用傳統的方式都會報bad參數的錯誤,調試好久都未果,個人經驗是,採用post方式,若是有特殊字符的 須要用 ‘’ 包含起來,好比上述的。
下面的代碼中wgetPost是封裝了一個將請求文件存到指定目錄的功能,文件名命名方式爲 debug_時間_全局的自增字段。
第一行請求變量參數裏有特殊字符,後面跟着的字符串也須要用‘’包含起來,具體爲何,應該是shell的解釋器就是這樣規定的,‘’小括號裏不能包含變量
wgetPost ${global_log_url}'logDebug?' ${global_project_log_debug_path}/ "debug_"$(date +%Y-%m-%d-%H-%M-%S)"_${global_debug_file_log_num}" ${inner_post_data}
#wget簡單封裝
#inner_url: 訪問地址
#inner_dir: 目錄
#inner_file: 文件名稱
#inner_post_data 請求的數據
wgetPost()
{
inner_url=$1
inner_dir=$2
inner_file=$3
inner_post_data=$4
#容錯處理
mkdir -p -m 777 ${inner_dir}
wget --post-data="${inner_post_data}" ${inner_url} -O ${inner_dir}${inner_file}".bk" -o /dev/null
inner_bytes=$(du -s ${inner_dir}${inner_file}.bk | awk '{print $1}')
if [ $inner_bytes -ne 0 ];then
cp -rf ${inner_dir}${inner_file}.bk ${inner_dir}${inner_file}
else
echo "wget ${inner_url} failed"
fi
}
3.sed命令在處理特殊字符替換的時候處理
sed –i ‘s/a/b/g’ 通常是這種方式,可是若是遇到要替換的字符或者被替換的字符有*_/ \的時候,就不適用了,解決的方式是利用#號
能夠通用點,就是將源字符串,替換爲目標字符串
source_str="abc" target_str="xxoo" sed -i "s#${source_str}#${target_str}#g" str.txt
4.合理的代碼編程規範
編碼規範很重要,v1.0版本寫的比較隨意,變量名比較混亂,維護花時間,
v2.0注意這個問題,目前的規範是:
1.全部的靜態變量 前綴爲 static_xx_xx
2.全部的全局變量 前綴爲 global_xx_oxx
3.參數爲 in_xx_xx
4.方法內的局部變量爲 inner_xxdf
5.方法的命名規則遵循通俗易懂
6.模塊化操做,講究代碼
5.目錄的權限問題
目錄的權限問題是個很是頭疼的問題,由於全部的操做爲root操做,若是控制到很是精細力度的權限,這塊都要頭疼死,在v2.0穩定的基礎上,保證自動部署系統的如期完成,頂級目錄不開放修改,子目錄爲777權限,任何人能夠修改,等自動部署系統前臺完成後,就能夠徹底回收權限了
6.日誌記錄的級別
日誌這個東西很重要,v1.0的版本是採用打印到控制檯的方式
v2.0採用方式是進行級別控制 ,分爲debug 和error 方式,debug模式有開關配置,error模式之間輸出,而且經過wget方式入庫,及時反饋到前臺
7.應用服務器及依賴環境的準備方式
依賴環境也很重要,自動部署講究一個自動部署,統一規範,可是線上的版本不少,好比jdk有1.5,1.6,1,7 同時 tomcat也會有各類版本,memcache等都各不相同。爲了統一,首先取線上穩定的tomcat版本清理後做爲基礎版本,例如tomcat.7.39.tar.gz,解壓後利用腳本動態更改配置後就可使用,還有jdk的安裝目錄等,如今的作法就是 把線上的版本都收集起來,經過後臺網頁工具進行選擇,自定義配置,首先應用環境的基礎版本是清潔版本,配置文件已經進行過優化,只須要替換幾個常量便可,這裏完成的是,1.tomcat的端口號,關閉端口,啓動時的jdk目錄,自啓動腳本的tomcat-home等