函式名稱作為循環中的變數
概述:我將變數保存在配置文件中,稍後再呼叫它們。
每個名為 FailOverVM 的條目旁邊都有一個數字,例如 FailOverVM1,我想檢查它是否有數據並生成一個名為 FailOverVM1() 的函式,該函式稍後在腳本中啟動 $FailOverVM1Name,恰好是“Plex Server”
我可以像 StartVM1() 一樣手動完成它並且我可以工作,但我可能會在以後擴展到 15 個並希望它進行相應的調整。
為了澄清,我可以稍後使用 Case 語句啟動 VM,但我不能圍繞本身就是一個變數的變數。我希望我沒有混淆任何人。也許我讓這種方式比它現在或需要的更複雜。
#!/bin/bash . "${BASH_SOURCE%/*}/configlocation.conf" . $Configuration checkVM1=$(nc -vvz $FailOverVM1IP $FailOverVM1Port 2>&1) VMCount=$(grep "FailOverVM.Name" /media/VirtualMachines/Current/Configuration.conf | wc -l) pinggateway=$(ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error = error) STATE="error"; while [ $STATE == "error" ]; do #do a ping and check that its not a default message or change to grep for something else STATE=$(ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error) #sleep for 2 seconds and try again sleep 2 done for i $VMCount; do if [ -z "$FailOverVM$VMCountName" ]; echo "$FailOverVM$VMCountName" fi done StartVM1(){ if [[ $checkVM1 = "Connection to $FailOverVM1IP $FailOverVM1Port port [tcp/*] succeeded!" ]]; then echo '$FailOverVM1Name is up' else echo "$FailOverVM1Name down" su -c 'VBoxManage startvm $FailOverVM1Name -type headless' vbox fi }
到目前為止我在測試腳本中的進展情況
#!/bin/bash . "${BASH_SOURCE%/*}/configlocation.conf" . $Configuration Pre='$FailOverVM' post="FailOverVM" name="Name" VMCount=$(grep "FailOverVM.Name" $Configuration | wc -l) #Count entires in config file wirn FailOverVM*Name while [[ $i -le $VMCount ]] do #if [ -z $Pre$i"Name" ];then #If the variable $FailOverVM*Name is not blank $post$i=$Pre$i$Name echo "$post$i" #print it #else # echo $Pre$i"Name" "was empty" #fi ((i = i + 1)) done
輸出:
./net2.sh: line 11: FailOverVM=$FailOverVM: command not found FailOverVM ./net2.sh: line 11: FailOverVM1=$FailOverVM1: command not found FailOverVM1 ./net2.sh: line 11: FailOverVM2=$FailOverVM2: command not found FailOverVM2 ./net2.sh: line 11: FailOverVM3=$FailOverVM3: command not found FailOverVM3 ./net2.sh: line 11: FailOverVM4=$FailOverVM4: command not found FailOverVM4 ./net2.sh: line 11: FailOverVM5=$FailOverVM5: command not found FailOverVM5 ./net2.sh: line 11: FailOverVM6=$FailOverVM6: command not found FailOverVM6
這裡的問題是沒有 $ FailOverVM without a number beside it, and what is up with “command not found FailOverVM5” (or any other number) I didn’t know I issued one. But the biggest problem is its not grabbing the variable $ FailOVerVM* 形成配置文件。我需要它用於 func 循環。
帶有@dave_thompson_085 幫助的新修改腳本
#!/bin/bash . "${BASH_SOURCE%/*}/configlocation.conf" . $Configuration for i in ${!FailOverName[@]}; do selip=FailOverIP[${i}] selport=FailOverPort[${i}] checkVM[$i]=$(nc -vvz ${!selip} ${!selport} 2>/devnull) echo ${!selip} echo ${!selport} echo FailOverName[${i}] done StartVM() { # first argument to a function is accessed as $1 or ${1} selname=FailOverName[${i}] if [[ checkVM[$i] =~ 'succeeded' ]]; then # only need to check the part that matters echo number $i name ${!selname} already up else echo starting number $i name ${!selname} echo su -c "VboxManager startvm '${!selname}' -headless" vbox # note " because ' $ fi } #done StartVM 1 # and StartVM 2 # etc
輸出
root@6120:~/.scripts# ./net2.sh -v 192.168.1.6 32400 FailOverName[1] 192.168.1.5 80 FailOverName[2] 192.168.1.7 80 FailOverName[3] 192.168.1.1 1030 FailOverName[4] starting number 4 name finch su -c VboxManager startvm 'finch' -headless vbox starting number 4 name finch su -c VboxManager startvm 'finch' -headless vbox root@6120:~/.scripts#
配置文件
# FailOverVM1IP='192.168.1.6' FailOverVM1Port='32400' FailOverVM1Name='Plex Server' FailOverVM1NASHDD='/media/VirtualMachines/Current/Plex\ Server/Plex\ Server.vmdk' FailOverVM1LocalHDD='/home/vbox/VirtualBox\ VMs/Plex\ Server/Plex\ Server.vmdk' FailOverVM2IP='192.168.1.7' FailOverVM2Port='32402' FailOverVM1Name='Plex Server2' FailOverVM2NASHDD='/media/VirtualMachines/Current/Plex\ Server/Plex\ Server.vmdk' FailOverVM2LocalHDD='/home/vbox/VirtualBox\ VMs/Plex\ Server/Plex\ Server.vmdk' FailOverVM3IP='192.168.1.8' FailOverVM3Port='32403' FailOverVM3Name='Plex Server3' FailOverVM3NASHDD='/media/VirtualMachines/Current/Plex\ Server/Plex\ Server.vmdk' FailOverVM3LocalHDD='/home/vbox/VirtualBox\ VMs/Plex\ Server/Plex\ Server.vmdk' FailOverVM4IP='192.168.1.9' FailOverVM4Port='32404' FailOverVM4Name='Plex Server4' FailOverVM4NASHDD='/media/VirtualMachines/Current/Plex\ Server/Plex\ Server.vmdk' FailOverVM4LocalHDD='/home/vbox/VirtualBox\ VMs/Plex\ Server/Plex\ Server.vmdk' FailOverVM5IP='192.168.1.10' FailOverVM5Port='32405' FailOverVM5Name='Plex Server5' FailOverVM5NASHDD='/media/VirtualMachines/Current/Plex\ Server/Plex\ Server.vmdk' FailOverVM5LocalHDD='/home/vbox/VirtualBox\ VMs/Plex\ Server/Plex\ Server.vmdk' FailOverIP[1]=192.168.1.6 FailOverName[1]=robin FailOverPort[1]=32400 FailOverIP[2]=192.168.1.5 FailOverName[2]=bluejay FailOverPort[2]=80 FailOverIP[3]=192.168.1.7 FailOverName[3]=sparrow FailOverPort[3]=80 FailOverIP[4]=192.168.1.1 FailOverName[4]=finch FailOverPort[4]=1030 VM1LogDirLogDir='/media/VirtualMachines/Logs/Plextstart' PlexServerIP='192.168.1.6' PlexPort='32400' mydate=`date '+%Y-%m-%d_%H%M'` rsyncfrom= NASPlexvmHDD='/media/VirtualMachines/Current/Plex\ Server/Plex\ Server.vmdk' LocalPlexvmDHDD='/home/vbox/VirtualBox\ VMs/Plex\ Server/Plex\ Server.vmdk' PlexVMname='Plex Server' PlexStartLogDir='/media/VirtualMachines/Logs/Plextstart' RouterIp='192.168.1.1'
所以它會看到所有的虛擬機,但只執行最後一次和兩次。
#!/bin/bash . "${BASH_SOURCE%/*}/configlocation.conf" . $Configuration for i in ${!FailOverName[@]}; do selip=FailOverIP[${i}] selport=FailOverPort[${i}] checkVM[$i]=$(nc -vvz ${!selip} ${!selport} 2>&1) echo ${!selip} echo ${!selport} #echo ${i} #done StartVM() { # first argument to a function is accessed as $1 or ${1} selname=FailOverName[${i}] if [[ $checkVM[$i] =~ 'succeeded' ]]; then # only need to check the part that matters echo number $i name ${!selname} already up else echo starting number $i name ${!selname} echo su -c "VboxManager startvm '${!selname}' -headless" vbox # note " because ' prevents the variable expansion fi } StartVM done
注意:檢查 VM 是否已經在執行還不起作用,但這不是我問的問題,所以這符合標準。
旁白:您可以
wc -l
通過使用grep -c FailoverVM.Name configfile
.但是,如果您想使用超過 9 位十進制的數字(例如 123456789abcdef),您的模式需要處於擴展模式
FailoverVM[0-9][0-9]?Name
或FailoverVM[0-9]{1,2}Name
處於-E
擴展模式。也是
for i $VMCount
語法錯誤;我假設你的意思是for i in $(seq $VMCount)
。您可以在 bash 中使用(bang) 和另一個包含名稱的變數間接讀取變數:
!
for i in $(seq $VMCount); do selname=FailoverVM${i}Name selip=FailoverVM${i}IP selport=FailoverVM${i}Port echo name ${!selname} is IP ${!selip} and port ${!selport} done
這與其說是一個大笨蛋,
eval
但仍然很笨拙。但是您不能以這種方式設置變數,因此您應該為此使用數組。而且您不能對函式執行此操作,因此請編寫一個接受參數的函式來告訴它要使用哪個(一組)變數:for i in $(seq $VMCount); do selip-Failover${i}IP selport=Failover${i}Port checkVM[$i]=$(nc -vvz ${!selip} ${!selport} 2>/devnull) } StartVM() { # first argument to a function is accessed as $1 or ${1} selname=FailoverVM${1}Name if [[ checkVM[$1] =~ 'succeeded' ]] # only need to check the part that matters then echo number $1 name ${!selname} already up else echo starting number $1 su -c "VboxManager startvm ${!selname} -headless" vbox # note " because ' prevents the variable expansion fi ] ... StartVM 1 # and StartVM 2 # etc
OTOH,如果您可以更改配置以對此類所有內容使用數組變數
FailoverIP[1]=10.255.1.1 FailoverName[1]=robin FailoverIP[2]=10.255.2.2 FailoverName[2]=bluejay etc
這將使一切變得更簡單。然後你不需要重新 grep 文件來計算條目,你可以使案例如
${#FailoverName[@]}