Nombre Func como variable en bucle

Descripción general: guardo mi variable en un file de configuration y los llamo más tarde.

Cada input con el nombre FailOverVM tiene un número al lado como FailOverVM1 y quiero verificar si tiene datos y generar una function llamada FailOverVM1 () que más tarde en el script inicia $ FailOverVM1Name, que pasa a ser 'Servidor Plex'

Puedo hacerlo manualmente como StartVM1 () y yo trabajo, pero puedo expandirme a 15 más tarde y quiero que se ajuste en consecuencia.

Para aclarar, puedo iniciar la máquina virtual con una statement Case más adelante y tener, pero no puedo entender la variable que en sí misma es una variable. Espero no haber confundido a nadie. Tal vez estoy haciendo esta manera más complicado de lo que es o necesita ser.

#!/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 } 

Donde he llegado tan lejos en un script de testing

 #!/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 

Salida:

 ./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 

El problema aquí es que no hay $ FailOverVM sin un número al lado, y qué pasa con "command no encontrado FailOverVM5" (o cualquier otro número) No sabía que emití uno. Pero el mayor problema es no agarrar la variable $ FailOverVM * del file de configuration. Lo necesito para el bucle de func.



Nueva secuencia de commands modificada con @ dave_thompson_085 ayuda

 #!/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 

Salida

 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# 

Archivo de configuration

 # 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' 

Así que ve todos los vms pero solo está ejecutando el último y el doble en eso.



 #!/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 

Nota: La comprobación de si VM ya se está ejecutando aún no funciona, pero esa no fue la pregunta que hice, por lo que cumple con los criterios.

Aparte: puede eliminar wc -l usando grep -c FailoverVM.Name configfile .
Pero si desea utilizar numbers por encima de 9 decimales (por ejemplo, 123456789abcdef), su patrón debe ser FailoverVM[0-9][0-9]?Name o FailoverVM[0-9]{1,2}Name en -E extendido modo.
También for i $VMCount es un error de syntax; Supongo que quiere decir for i in $(seq $VMCount) .


¡Puedes leer una variable indirectamente en bash con ! (bang) y otra variable que contiene el nombre:

 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 

que es less de un trabuco que eval pero sigue siendo torpe. Pero no puede establecer una variable de esta manera, por lo que debe usar una matriz para eso. Y no puede hacer esto para las funciones, por lo tanto, escriba una function que acepte un argumento para indicarle qué (set de) variables usar:

 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 si puedes cambiar la configuration para usar variables de matriz para todo esto

 FailoverIP[1]=10.255.1.1 FailoverName[1]=robin FailoverIP[2]=10.255.2.2 FailoverName[2]=bluejay etc 

eso haría todo mucho más simple. Y luego no necesita volver a grep el file para contar las inputs, solo puede usar, por ejemplo, ${#FailoverName[@]}