![루프 내 변수로서의 함수 이름](https://linux55.com/image/91280/%EB%A3%A8%ED%94%84%20%EB%82%B4%20%EB%B3%80%EC%88%98%EB%A1%9C%EC%84%9C%EC%9D%98%20%ED%95%A8%EC%88%98%20%EC%9D%B4%EB%A6%84.png)
개요: 구성 파일에 변수를 저장하고 나중에 호출합니다.
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과 두 번만 실행합니다.
#!/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자리 이상의 십진수(예: 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[@]}