隨著docker的流行,docker的應用越來越多,工作中肯定少不了,但個人感覺docker的有些命令需要的參數有點多,比如運行一個容器,–name給容器起名,-d後台運行等等。根據個人習慣,一般很多參數都是固定的,沒必要每次操作都敲一遍,工作效率特別低。特別是對於不熟悉docker的人員,比如營運人員,這時候給他們提供一個部署指令碼是很有必要的,因為越是能簡化他們的工作,他們找我們解決問題的機會就更少。
前段時間實現了一個很簡單的部署指令碼,可以簡化docker安裝、容器運行等工作,根據傳給指令碼的第一個參數作為命令而進行不同的處理。對於不同的命令在shell中使用case來進行匹配不同的處理,後來發現隨著命令的增多,case匹配的代碼越來越長,而且需要修改多處地方,修改很費勁,畢竟處理實現功能處理外,還需要提供一些協助資訊。
這兩天一直想著怎麼改進這指令碼怎麼寫,讓它可以很好的擴充,添加新命令更簡單。經過一個晚上的思考及在網上搜尋,最終主要使用map簡化case操作,最後寫成的指令碼個人還是挺滿意的,添加一個命令時不會修改原有的代碼,只需要在同一個地方添加新代碼,在map中添加協助資訊,另外再對應添加一個處理函數就好。具體實現如下,指令碼中只是添加了幾個簡單命令:
#!/bin/bash#聲明一個命令協助容器,運行指令碼時輸入的第一個參數當作命令,根據命令做不同處理declare -A cmdHelpMap=()redColor="\033[31m"normalColor="\033[0m"yellowColor="\033[33m"scriptName=$0 #啟動並執行指令碼名字inputArgsNum=$# #運行指令碼時輸入參數的個數#列印資訊,對列印資訊進行尋找指令碼名字,紅色列印需要傳遞的參數function println(){ findScriptName=0 #是否找到指令碼名字 index=0; #遍曆列印資訊 for arg in $@ do if [ ${arg} = ${scriptName} ] then findScriptName=1 echo -en "\n\t" fi if [ ${index} -gt ${inputArgsNum} ] then echo -en ${redColor} fi echo -en "${arg} " if [ ${findScriptName} -eq 1 ] then let index++ fi done echo -e ${normalColor}}#參數處理,判斷輸入參數個數與協助資訊中需要的參數個數是否相等,不相等則列印協助資訊並退出function parameterHandling(){ findScriptName=0 argsNum=0; key=$1 helpMsg=${cmdHelpMap[$key]} #遍曆協助資訊總計需要輸入的參數個數,協助資訊中出現指令碼名字後開始統計, #自動以空格分割協助資訊進行遍曆 for msg in ${helpMsg} do if [ ${findScriptName} -eq 1 ] then let argsNum++ fi if [ ${msg} = ${scriptName} ] then findScriptName=1 fi done #參數個數不相等處理 if [ ${inputArgsNum} -ne ${argsNum} ] then println ${helpMsg} exit fi}#確認操作function confirm(){ echo -ne "${yellowColor}$* ?[y/n]${normalColor}" read input if [ -z ${input} ] then exit fi if [ ${input} != "y" ] then exit fi}##############################################################################################添加命令只需要兩步:#1、以命令為key,往cmdHelpMap中添加協助資訊#2、以命令為函數名定義命令處理函數#例如以下的help命令#help命令cmdHelpMap["help"]="查看協助資訊: ${scriptName} help"function help(){ inputArgsNum=0 println "Usage:" preFunc=${FUNCNAME[1]} number=1; for key in ${!cmdHelpMap[@]} do println ${number}.${cmdHelpMap[$key]} let number++ done}#install命令cmdHelpMap["install"]="安裝docker: ${scriptName} install"function install(){ docker -v if [ $? -eq 0 ]; then confirm Docker已安裝,確認是否繼續安裝 fi curl -sSL https://get.daocloud.io/docker | sh}#run命令cmdHelpMap["run"]="運行容器: ${scriptName} run [imageName:imageTag] [hostPort:containerPort]"function run(){ image=$2 containerName=${image/:/-} port=$3 docker run -d --name ${containerName} --restart=always -p ${port} ${image} if [ $? -ne 0 ]; then println ${redColor}運行${containerName}失敗, 請檢查鏡像${image}是否存在 exit fi}#rmi命令cmdHelpMap["rmi"]="刪除鏡像: ${scriptName} rmi [imageName:imageTag]"function rmi(){ image=$2 confirm 確定刪除鏡像${image} docker rmi ${image} if [ $? -ne 0 ]; then println ${redColor}刪除鏡像失敗, 請檢查鏡像${image}是否存在 fi}#rm命令cmdHelpMap["rm"]="刪除容器: ${scriptName} rm [imageName-imageTag]"function rm(){ containerName=$2 docker rm -f ${containerName} if [ $? -ne 0 ]; then println ${redColor}刪除容器失敗, 請檢查容器${containerName}是否存在 fi}##############################################################################################如果第一個參數為空白或者不存在map中,則預設第一個參數為helpcmd=$1if [ -z $cmd ] || [ -z "${cmdHelpMap[$cmd]}" ]then if [ $# -ne 0 ] then println ${redColor}無效參數:$* fi cmd="help" inputArgsNum=1fi#參數處理parameterHandling $cmd#執行相應處理函數$cmd $*
指令碼直接儲存為deploy.sh,以下是一些簡單操作提示資訊的效果圖: