Backing up a Vmware ESXi v5 Virtual Machine from the command line

 In VMWare

Binary Royale is an IT consultancy company based in the East Midlands. We spend all of our time with clients, helping them to make good decisions about their IT. When we come across issues that would be useful to others we “try” to post the answers on our website – www.binaryroyale.com . We cover Derby and Derbyshire, Nottingham and Nottinghamshire mainly, but do also have clients further afield. Please browse our website to see what we offer – thanks, and enjoy the blog


Brief : I have the ability to shutdown VMware machines at night, so I decided to write a script to do just this AND backup the data within the VM. Here’s how I went about it

My ESXi server is already SSH enabled, using the console, so I am able to SSH into my ESXi box

If you haven’t already done this, follow the instructions posted here on the VMWare site

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1017910

Once SSH is enabled follow the instructions below

    1. So firstly connect to your ESXi server using an SSH client – I use putty
    2. Now we need to list the VM’s running on your host, so we can retrieve their World Names

esxcli vm process list

    1. Next I wanted to check that I could definately power down my VM in question. Using the correct World Name, retrieved from the above output, I was able to gracefully shutdown my VM

esxcli vm process kill –type=soft –world-id=1234567

My VM started to power down – nice

    1. The next step for me was to manually run through the commands, my script will ultimately execute step by step to make sure each bit worked. So first up was copying the files from their current location to a backup location.The locations of the disks, from a GUID perspective, can be seen in the vSphere Client, under HOST, Configuration tab, Storage Link. I was then able to backup the files
[highlight]mkdir /vmfs/volumes/GUID of backup volume/backups/VMName[/highlight] # e.g. mkdir /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-AM
[highlight]cp /vmfs/volume/GUID of source datastore/GUID of VM GUID* /vmfs/volumes/GUID of backup volume/backups/VMName[/highlight] # e.g. cp /vmfs/volumes/PersistentDisks-3x450sR5/BR-DESK-AM-vdm-user-disk-D-9898779b-33e0-4635-93e3-740e70827731* /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-AM/

[notice]Point to note here. When you have multiple disks within a VM they may well be stored in different volumes (DataStores)[/notice] You need to make sure your COPY commands are backing up the data you want. In my example I ONLY wanted the D: of the VM. Hence I simply found its location and GUID for this drive and backed up the files that were in there.

    1. Now to start putting the script together and inserting the commands we have issued here

touch backupdesktops.sh
chmod 740 backupdesktops.sh
echo ‘#/!bin/bash’ > backupdesktops.sh
echo ‘# This script contains commands required to’ >> backupdesktops.sh
echo ‘# 1. Shutdown a few Virtual Machines’ >> backupdesktops.sh
echo ‘# 2. Copy the VM Data from its source location to a backup location’ >> backupdesktops.sh
echo ‘# 3. And leave them off as users will start them up when they login next’ >> backupdesktops.sh
echo ‘# ‘ >> backupdesktops.sh
echo ‘# ‘ >> backupdesktops.sh
echo ‘# ‘ >> backupdesktops.sh
echo ‘# Shutdown Andys Desktop’ >> backupdesktops.sh
echo ‘esxcli vm process kill –type=soft –world-id=1234567’ >> backupdesktops.sh
echo ‘# Shutdown JKs Desktop’ >> backupdesktops.sh
echo ‘esxcli vm process kill –type=soft –world-id=1234567’ >> backupdesktops.sh
echo ‘# Wait for the desktops to shutdown properly – 2 mintues’ >> backupdesktops.sh
echo ‘sleep 2m’ >> backupdesktops.sh
echo ‘#mkdir /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups’ >> backupdesktops.sh
echo ‘mkdir /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-AM’ >> backupdesktops.sh
echo ‘rm /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-AM/*’ >> backupdesktops.sh
echo ‘cp /vmfs/volumes/4f9fa82d-736125a7-160a-68b59977c352/BR-DESK-AM* /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-AM/’ >> backupdesktops.sh
echo ‘mkdir /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-JK’ >> backupdesktops.sh
echo ‘rm /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-JK/*’ >> backupdesktops.sh
echo ‘cp /vmfs/volumes/4f9fa82d-736125a7-160a-68b59977c352/BR-DESK-JK* /vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups/BR-DESK-JK/’ >> backupdesktops.sh

So far I’ve shut down a couple of VM’s, waited a couple of minutes, created a backup folder, then copied the contents of my VM folder to my backup datastore.

  1. OK – The above code is quite basic. You can see that for starters I am echo’ing the commands into the backup script. From this point forth I’m simply going to write out the script as though you were editing it directly. Now that you can see the basics of it, you may want to delete what’s been done so far and simply copy the code below into a new backup script altogether. I’ll paste it in below and then explain it’s operation in more detail. The width of the page below is limited so you can download the script from the link at the bottom of this post. If you try to copy and paste it from the table below, you’ll miss important bits from the script.
#/!bin/bash.
#/!bin/bash.
# This script contains commands required to.
# 1. Shutdown a few Virtual Machines.
# 2. Copy the VM Data from it.s source location to a backup location.
# 3. And leave them off as users will start them up when they login next.
# 4. This program loops through the users one at a time
# 5. writes logs into /var/log/backupdesktops.log
# .

# System Variables
TODAY=$(date -u +%h%d-%Y)
TIMENOW=$(date -u +%h%d-%Y@%k:%M)
BCKROOTDIR=/vmfs/volumes/4f785d87-d701596e-bdf7-68b59977c354/Backups
LOGFILE=/var/log/backupdesktops.log

# MAKE A BACKUP DIRECTORY
if [ ! -d "$BCKROOTDIR" ]; then
mkdir $BCKROOTDIR
fi
echo Starting Backup at $TIMENOW >> $LOGFILE

CreateBackup() {
# Has a backup already been created today
WorldID=""
BCKDIR=$BCKROOTDIR/$DESKTOPNAME
echo Starting Backup for $DESKTOPNAME at $TIMENOW >> $LOGFILE
if [ ! -d "$BCKDIR/$TODAY" ]; then

# picks out the world ID for a given desktop(display) name
WorldID=$(esxcli vm process list | grep -iA 1 $DESKTOPNAME | grep -e World | awk '{print $3}')

if [[ $WorldID ]]; then
# Shutdown Users Desktop
esxcli vm process kill --type=soft --world-id=$WorldID
# Wait 2 minutes before proceeding - gives time to let the desktop shutdown
sleep 2m
fi

# make dir and copydata
if [ ! -d "$BCKDIR" ]; then
mkdir $BCKDIR
fi
rm -rf $BCKDIR/*
mkdir $BCKDIR/$TODAY
for files in $(find /vmfs/volumes/PersistentDisks-3x450sR5/* -type f -name *$DESKTOPNAME*)
do
cp $files $BCKDIR/$TODAY
echo $files copied into $BCKDIR/$TODAY >> $LOGFILE
done
echo Backup for $DESKTOPNAME Completed at $TIMENOW >> $LOGFILE

else
echo Backup Already exists for $DESKTOPNAME today - Exiting at $TIMENOW >> $LOGFILE
fi

}

# BINARY ROYALE
#** Andy McCulloch
DESKTOPNAME=BR-VDS-AM
# run the backup
CreateBackup

#** Jonathan King
DESKTOPNAME=BR-VDS-JK
# run the backup
CreateBackup

echo Completed Backup at $TIMENOW >> $LOGFILE

This is how the script works

    • The Variables – One sets todays date, One sets todays time & date, One defines where I want the backups to reside and the final variable says the location I want the logging to go to
    • Please create the logfile using

touch pathtologfile/logfilename
e.g. touch /var/log/backupdesktops.log

    • The first part of the script simply creates the backup directory, as you’ve defined in variable 3. You could omit this from the script and just create the backdir manually. I like to have these things left in, so that IF the backup volume was emptied, somehow, it wouldn’t fall over when the script was run again
    • The second part of the script is a function called “CreateBackup” – For every desktop I defined, lower down in the script, I call CreateBackup. You could do this differently and not use a function. You could create a list of desktops and loop through them. I was experimenting 🙂 . I think it works well and I can # out certain desktops, at the bottom of the script, If I don’t want to back them up for any reason
    • The Function – CreateBackup
      • I set the World ID variable to NULL
      • I set the backupdirectory name to include the desktop name – I’m saying desktop here, but this can simply be read as virtual machine – I’m backing up desktops
      • If there is no backup for today, I continue
      • I write into the logfile throughout this script, as bits are carried out
      • esxcli vm list process pulls a list of CURRENTLY POWERED ON VMs – I am manipulating this list to search for a DESKTOPNAME, which I define at the end of the script, and then simply pull out the WorldID for this desktop. This way I can power down DEFINED desktops, one by one, as I’m about to back them up. If they are OFF, then they simply get backed up.
      • The next step shuts down the desktop in question using the WorldID collected from the command above
      • I’m deleting the backups prior to this one I about about to take – YOU MAY WANT TO DO THIS DIFERRENTLY – In my environment, there is no point in having old backups. This step deletes all the backups created for this desktop
      • Then a new backup DIR for today is created
      • A list of ALL the files within this VM’s source directory, which in my case is in a Persistent Disks Volume, is created.
      • One by one (do for files in) the CP command copies the files from the source volume/dir to the backups dir -> $BCKDIR/$TODAY
      • Completed for “VM x” is written to the LOGFILE
      • If there is already a backup, for this VM, TODAY, then the step is skipped and a log is written
    • This is the end of the CreateBackup Function
    • The final part of the script is detailing the different VM’s I want to backup and calling the above function

# BINARY ROYALE
#** Andy McCulloch
DESKTOPNAME=BR-VDS-AM
# run the backup
CreateBackup

      • I have made it that the DESKTOPNAME is case inspecific
      • And finally the last entry is made into the logfile
      • And thats it. Simply define the virtual machine names and call the CreateBackup function
[notice]Remember that in my example I am simple backing up ONE of the disks. In my case it’s the D: on these desktops. For more disks you’ll need to amend the script to CP more [/notice]

NEXT AND FINAL PIECE – Scheduling the Job to Run

Change the permissions on the cron file

chmod 644 /var/spool/cron/crontabs/root

Make a backup of the root cron job

cp /var/spool/cron/crontabs/root /var/spool/cron/crontabs/root.backup

Edit your backup

vi /var/spool/cron/crontabs/root.backup

add this to it – Note that I want this job to run on weekdays ONLY 1-5, at 5mins past 1am.

5 1 * * 1-5 /usr/bin/backupdesktops.sh > /dev/null

Move the backup over the top of the original

mv /var/spool/cron/crontabs/root.backup /var/spool/cron/crontabs/root

Change the permissions back on the cron file

chmod 444 /var/spool/cron/crontabs/root

NOW KILL THE CRON DAEMON

/bin/kill $(cat /var/run/crond.pid)

And start it back up again

crond

You will need to update the root cron file if you reboot. If you do not wish to edit this file, everytime you restart, then you can follow the instructions here.
http://communities.vmware.com/docs/DOC-8760

I just didn’t feel safe doing it.

All the best and enjoy – Jonathan

vmware-logo3-300x180[divider] [wpdm_file id=1 title=”true” desc=”true” ]

Contact Us

Call us on: 01332 890460 or Send us an email and we'll get back to you, asap.

Not readable? Change text. captcha txt