while loop issues

Hi guys,

Been sifting through these forums for awhile, but never had an account or needed to post. Shoutouts to a great forum with heaps of useful info.

Now i consider myself a noob when it comes to linux and to bash scripting. I recently started to learn to use Vmware ESX server which uses redhat. Now I wanted to learn how to bash script so i set myself a goal, to write a bash script that would backup some files on the ESX server and then ftp them.

I got a working script going, not very pretty but it worked. I recently made some changes to it and now it isnt doing exactly what i was hoping. Basically I put alot of IF commands in to check if things were on the right track and if they werent they set a variable to 1. The whole script runs under a while loop that checks to see if that variable is 1. If so it stops.

For some reason, now even when i set variable to 1, the loop keeps running till it gets to the end of all the commands. then it stops. So my point is have i done something wrong, or am i misunderstanding how while loops work. Shouldn't it stop the momment its condition is met?

Hoping someone can point me in the right direction.


#!/bin/bash

function getvmstate {
vmware-cmd "$1" getstate|grep on|wc -l
}

function basename()
{
local name="${1##*/}"
echo "${name%$2}"
}

function dirname()
{
local dir="${1%${1##*/}}"
[ "${dir:=./}" != "/" ] && dir="${dir%?}"
echo "$dir"
}

function namename()
{
local name=${1##*/}
local name0="${name%.*}"
echo "${name0:-$name}"
}

function ext()
{
local name=${1##*/}
local name0="${name%.*}"
local ext=${name0:+${name#$name0}}
echo "${ext:-.}"
}

function vmclonerun {
perl /usr/bin/vmclone $1 $2
}

COUNT=0
#storage1="storage1"
storage1="4721f5a3-2dd43ff0-636d-000e0ce9b566"
storage2="4721f5bc-5cb4f268-06bb-000e0ce9b566"
VM="/vmfs/volumes/4721f5bc-5cb4f268-06bb-000e0ce9b566/winxpsp2-test-01/winxpsp2-test-02.vmx"
VMCDIR=`dirname $VM`
VMCNAME=`namename $VM`
VMCBKPNAME="$VMCNAME-bkp"
VMCBKPDIR="$VMCDIR-bkp"
FTPPATH="myftpserver"
FTPUSER="myusername"
FTPPASS="mypassword"
OLDNAME="$VMCBKPNAME-old"
DELNAME="$OLDNAME-del"
skip=0
preoff=0

# for vm in `vmware-cmd -l`
# do
skip="0"
while [ $skip != 1 ]
do

if [ `id -u` != "0" ]
then
echo "Sorry, you are not root. Script exiting."
exit 1
fi

if [ -s $VM ]
then
echo "VMX Exists"
if [ -r $VM ]
then
echo "VMX Readable"
else
echo "VMX NOT Readable"
echo "Skipping VM"
skip=1
fi
else
echo "VMX corrupted or not there"
echo "Skipping VM"
skip=1
fi

check=`dirname "$VM"|grep $storage1|wc -l`
#echo "Check: $check"
#echo "VM: $vm"
if [ $check -eq 0 ]
then

if [ `getvmstate $VM` -eq 1 ]
then
vmware-cmd $VM stop trysoft
else
echo "VM OFF!"
echo "Proceeding with clone..."
preoff="1"
fi

while [ `getvmstate $VM` -eq 1 ]
do
# echo "Count $COUNT"
echo "Waiting for VM to shutdown...."
sleep 10
let COUNT=COUNT+1

if [ $COUNT -eq 12 ]
then
echo "VM Shutdown taking too long. Skipping VM."
skip="1"
fi

done

if [ `getvmstate $VM` -eq 0 ]
then

if [ -d "$VMCBKPDIR" ]
then
echo "Deleting old clone..."
rm -rf $VMCBKPDIR
fi

if [ -d "$VMCBKPDIR" ]
then
echo "Clone stil exists. Problem deleting. Skipping VM."
skip="1"
else
cd /
cd $VMCDIR
cd ../
echo "Cloning..."
vmclonerun $VMCNAME $VMCBKPNAME
cd /
echo "Clone complete."

if [ $preoff = 1 ]
then
echo "VM Left Off"
else
echo "Starting VM"
vmware-cmd $VM start
fi

echo "FTP Transfer started"


/usr/bin/ftp -n << !
open $FTPSERVER
user $FTPUSER $FTPPASS
prompt off
binary
lcd /
lcd $VMCBKPDIR
cd $FTPPATH
rename $OLDNAME $DELNAME
rename $VMCBKPNAME $OLDNAME
mkdir $VMCBKPNAME
cd $VMCBKPNAME
mput *
quit
!

echo "FTP Transfer complete"


echo "Removing local clone"
rm -rf $VMCBKPDIR
skip="1"
fi



else
echo "Unknown Error - VM state is not off"
skip="1"
fi

else
echo "In Storage 1 DISREGARDED"
skip="1"
fi

done
#done

The while loop only does the evaluation at the top of the loop, so if you go:

while thing
do
  blah
  stuff
  make thing not true
  some other stuff
done

It will do everything in the while loop once (inlcuding 'some other stuff') then get to the top and find 'thing' to be not true anymore.

Ah ok cheers for the response. So it was just my poor understanding of a while loop.

Ok, well one question then during the whole while loop can i run a command to prematurely end the loop?

or do i have to re-structure the script?

'break' will do that. I don't use it myself as I dislike breaking out of loops but that's just me :wink:

I'll stand up for using "break", very useful when encountering error conditions and you need to abort what you are doing.