Linux bash script for VMware: automated backup vm’s

Linux bash script for VMware: automated backup vm’s

Linux bash script for VMware: automated backup vm’s 150 150 Roderick Derks

Here is a script that I use to create backups of all of my VM's. There has been some evolution over time so I posted three versions. You can run these script after some adjustments on your VMware host server. For every VM the same routine is followed: stop, copy, start. To complete the backup procedure the backup that just was created is copied to a remote VMware server. So in case of a hardware failure you can start your VM's again on the remote machine. Be aware that this is not a hot backup, the VM's will be switched off.

What you have to know and do before starting this script?

  1. This script is a Linux bash script so the VMware host should be a linux os, not Windows. If you're running Windows then you can use the concept and program in DOS or VB or so. And you can use blat as a simple smtp email tool.
  2. I use the VMware server version. I don't know if this script works with other versions of VMware but I guess there shouldn't be any problems.
  3. Create a ssh key of the host server you are running the vm's on and install it on the backup server. This is very usefull so you don't have to use passwords in your scripts to log in when using ssh for backing up the vm files.
  4. Install the VMware tools on all VM's so they can be shut down using the command line tools on the vmware host server.
  5. Adjust the script to your situation. Change the variables in the script. And add your own email address and emailserver. If you don't receive the email try to send an email on the command line yourself or check your servers smtp settings.

I got three versions of the script and you can find them on these three pages.

(new stuff:
      vm_list="`vmware-cmd -l`"
      OLD_IFS="$IFS"
      IFS="
      "
 
     for vm in "$vm_list"; do
         …
     done

 

#! /bin/bash
# Roderick Derks
# www.r71.nl
# 20070227
#
# backup vmware's virtual machines to a remote computer
# 1. check if backupserver is running
# Actions 2, 3 and 4 are per vm:
# 2. stop the vm if it is running
# 3. local copy the vm files
# 4. start the vm if it was running
# 5. remote copy of the backups created in step 3
###################################################################

### day and hour
    DAY=$(date | cut -d" " -f1)
    HOUR=$(date|tr -s " "|cut -d" " -f4| cut -d":" -f1)
### logfile
    export LOGFILE="/var/log/backup_vmware_servers.log"
    if [ ! -e "${LOGFILE}" ]
       then touch "$LOGFILE" # create a new logfile if not present
    fi
### variables
    VM_HOST_SRC="alpedhuez.r71.nl"
    VM_HOST_REMOTE_DEST="bonette.r71.nl"
    VM_ROOT_SRC="/DATA/vmware/vmmachines"
    VM_LOCAL_BACKUP_DEST="/mnt/usbdrive01/Backup/vmware/vmmachines"
    VM_ROOT_REMOTE_DEST="/DATA/vmware/vmmachines"
    VM_REMOTE_DEST="${VM_HOST_REMOTE_DEST}:${VM_ROOT_REMOTE_DEST}"
    MAILSERVER="yourmailserver.yourmail.com"
    EMAILADDRESS="your_email_account@yourdomain.com"

###################################################################
### check local machine name
if [ $HOSTNAME != "${VM_HOST_SRC}" ]; then
   echo Hostname=${HOSTNAME}:
   echo "Dit script will only run on ${VM_HOST_SRC}"
   exit
fi

echo $HOSTNAME > ${LOGFILE}          # flush logfile and add data
date >> ${LOGFILE}
echo >> ${LOGFILE}

###################################################################

IFS=$'n' # needed to prevent problems with filenames containing spaces in arrays
for VM_PATH_FILE in $(find ${VM_ROOT_SRC} -type f -name *.vmx)
do

  echo VM: ${VM_PATH_FILE} | tee -a ${LOGFILE}
  echo | tee -a ${LOGFILE}

  ##
  ## stop vm's if they are running
  ##

  vmware-cmd ${VM_PATH_FILE} getstate|grep -q "getstate() = on"
  if [ $? -eq 0 ]; then
     echo "Shutting down VM at `date`." | tee -a ${LOGFILE}
     #array0=( "${array0[@]}" "${VM_PATH_FILE}" ) # add to array, these vm's  will  be started later on
     BOOT="1"
####     vmware-cmd ${VM_PATH_FILE} stop soft >> ${LOGFILE}
  else
     echo "VM is not running." >> ${LOGFILE}; echo "VM is not running."
     BOOT="0"
  fi

  ##
  ## start backup
  ##

  VM_PATH=`echo ${VM_PATH_FILE}|rev|cut -d"/" -f2-|rev` # remove last field (using rev to remove first field, is easier)
  echo VM_PATH: $VM_PATH

  echo "Starting local backup at `date`. (This is going to take a while…)" | tee -a ${LOGFILE}

  # Local rsync copy command (to a local disk)
  VM_ROOT_SRC_VMDIR=`echo ${VM_PATH}|awk -F "${VM_ROOT_SRC}" '{ print $2 }'`
  #echo rsync -avu ${VM_PATH}/ ${VM_LOCAL_BACKUP_DEST}${VM_ROOT_SRC_VMDIR}
####  rsync -avu ${VM_PATH}/ ${VM_LOCAL_BACKUP_DEST}${VM_ROOT_SRC_VMDIR} >> ${LOGFILE}

  echo Local backup finished at `date`. | tee -a ${LOGFILE}

  ##
  ## start VM if it was running
  ##

  if [ $BOOT -eq 1 ]; then
  echo "Starting VM" | tee -a ${LOGFILE}
####  vmware-cmd "${VM_PATH_FILE}" start >> ${LOGFILE}
  fi
  if [ $BOOT -eq 0 ]; then
  echo "VM wasn't running so it will not be started." | tee -a ${LOGFILE}
  fi

  echo | tee -a ${LOGFILE}

  echo "————————————————————" | tee -a ${LOGFILE}
done

date >> ${LOGFILE}
echo "All VM's have been backed up and started at `date`." | tee -a ${LOGFILE}

###################################################################

# check if remote server is up using return value: 1 is failed (down), 0 is success (up)
echo | tee -a ${LOGFILE}
echo Starting remote backup procedure. | tee -a ${LOGFILE}

ping ${VM_HOST_REMOTE_DEST} -c2|grep -q " 0% packet loss"
if [ $? -eq 0 ]; then
   echo
   echo ${VM_HOST_REMOTE_DEST} is up, ping test succeeded. | tee -a ${LOGFILE}

   # Copy local backup to a remote server.
   echo Remote backup started at `date`.. | tee -a ${LOGFILE}
####   rsync -avu -e ssh ${VM_LOCAL_BACKUP_DEST}/ ${VM_REMOTE_DEST} >> ${LOGFILE}
   echo Remote backup finished at `date`. | tee -a ${LOGFILE}

else
   echo
   echo ${VM_HOST_REMOTE_DEST} unreachable, ping failed: no remote backup. | tee -a ${LOGFILE}
fi

echo | tee -a ${LOGFILE}

###################################################################

##
## Mail
##

ping ${MAILSERVER} -c2|grep -q " 0% packet loss"
if [ $? -eq 0 ]; then
   echo
   echo ${MAILSERVER} is up, ping test succeeded. | tee -a ${LOGFILE}

else
   echo
   echo ${MAILSERVER} unreachable, ping failed: waiting for 90 seconds to give it some time to boot. | tee -a ${LOGFILE}

   sleep 90 # my mailserver is probably booting now so wait a little bit
   #exit 1
fi

echo "Sending e-mail to ${EMAILADDRESS}" >> ${LOGFILE}
date >> ${LOGFILE}          # logfile aanvullen
mail -s "VMWare backupscipt finished" ${EMAILADDRESS} <${LOGFILE}

exit 0

Roderick Derks

Liefhebber van fietsen, van het oplossen van IT puzzels, en van het delen van informatie om anderen te helpen.

All stories by:Roderick Derks

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Your Name (required)

Your Email (required)

Subject

Your Message

Your Name (required)

Your Email (required)

Subject

Your Message