最近使用shell編寫一個備份和替換f服務器程序的腳本replace.sh,初衷是為了節約人力的重復機械的勞動。在腳本編寫過程中,由于疏忽多打了一個空格,出現了一個不符合預期的情況。
1.先看一下出問題的replace.sh
清單1:replace.sh
1 #!/bin/sh 2 file="mv.sh" #日志清理腳本 3 bak="mv" 4 replace="scp" 5 hostPath="/data/kuyin_new/musicsearch/bin/logs" 6 #hostList=(172.16.72.50 172.16.72.56 172.16.72.58 172.16.72.76 172.16.72.78 172.16.72.96 172.16.72.98) 7 hostList=(172.16.72.50) 8 for host in ${hostList[*]} 9 do10 bakCmd= "ssh $host $bak ${hostPath}/$file ${hostPath}/${file}.bak" #先備份目標機器上的腳本,這里=之后多打了一個空格11 echo $bakCmd #這里先打印一下bakCmd命令,看一下12 #bash -c "$bakCmd"13 #replaceCmd="$replace $file ${host}:${hostPath}" #拷貝至目標機器14 #finalCmd="${bakCmd} ; ${replaceCmd}"15 #echo $replaceCmd16 #echo $finalCmd17 #bash -c "$finalCmd"18 done
執行腳本,運行結果如下:
多打了一個空格,之后bash replace.sh運行腳本,出現了不符合預期的情況:ssh 172.16.72.50 mv /data/kuyin_new/musicsearch/bin/logs/mv.sh /data/kuyin_new/musicsearch/bin/logs/mv.sh.bak(ssh $host $bak ${hostPath}/$file ${hostPath}/${file}.bak經過變量替換后的結果) 命令竟然執行了!而我的初衷是用echo查看這個命令組合的是不是正確,這條命令并不會被執行。那么為什么會出現這種情況呢?
為了找出問題,可以通過bash -x replace.sh運行腳本。“-x”選項使shell在執行腳本的過程中把它實際執行的每一個命令行顯示出來,并且在行首顯示一個”+”號。 “+”號后面顯示的是經過了變量替換之后的命令行的內容,有助于分析實際執行的是什么命令。 “-x”選項使用起來簡單方便,可以輕松對付大多數的shell變量任務,應把其當作首選的調試手段。執行bash -x replace.sh,結果如下:
可以看出,replace.sh中的第10行被拆成了2條命令(黃色框和紅色框共2條命令),因此ssh $host $bak ${hostPath}/$file ${hostPath}/${file}.bak才會被執行。下面去掉第10行多出的空格,看一下效果。
2. 正常的replace.sh
清單2:replace.sh
1 #!/bin/sh 2 file="mv.sh" #日志清理腳本 3 bak="mv" 4 replace="scp" 5 hostPath="/data/kuyin_new/musicsearch/bin/logs" 6 #hostList=(172.16.72.50 172.16.72.56 172.16.72.58 172.16.72.76 172.16.72.78 172.16.72.96 172.16.72.98) 7 hostList=(172.16.72.50) 8 for host in ${hostList[*]} 9 do10 bakCmd="ssh $host $bak ${hostPath}/$file ${hostPath}/${file}.bak" ##先備份目標機器上的腳本,去除了多余的空格,此時第10行就是一個命令11 echo $bakCmd12 #bash -c "$bakCmd"13 #replaceCmd="$replace $file ${host}:${hostPath}" #拷貝至目標機器14 #finalCmd="${bakCmd} ; ${replaceCmd}"15 #echo $replaceCmd16 #echo $finalCmd17 #bash -c "$finalCmd"18 done
運行結果如下:
因此,在編寫shell腳本時要格外注意空格。