ループ内変数としての関数名

ループ内変数としての関数名

概要:設定ファイルに変数を保存して後で呼び出します。

FailOverVMという各項目の横にはFailOverVM1と同じ数字があり、データがあることを確認し、後でスクリプトで「Plex Server」である$ FailOverVM1Nameを実行するFailOverVM1()という関数を作成したいと思います。

StartVM1()のように手動でこれを行うことができますが、それはうまくいきますが、後で15に拡張してそれに応じて調整したい場合があります。

明確にするために、後でCaseステートメントを使用して仮想マシンを起動できますが、変数自体が変数であることを理解できません。誰も混同しないでほしいです。おそらく私はこの方法を現在または必要なものよりも複雑にしているようです。

#!/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の横に数字がなく、「コマンドが見つかりませんFailOverVM5」(または他の数字)で何が起こっているかです。私が発行したのか全く分かりません。しかし、最大の問題は、設定ファイルから$ 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'

したがって、すべてのVMを表示できますが、最後のVMと2回だけ実行します。



#!/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がすでに実行されていることを確認することはまだ機能していませんが、私が尋ねる質問ではないため、基準を満たしています。

ベストアンサー1

ナレーター:をwc -l使用して削除できますgrep -c FailoverVM.Name configfile
ただし、9桁以上の10進数(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[@]}

おすすめ記事