Backup ESXi 5.x running virtual machine

Backup ESXi 5.x running virtual machine

Category : How-to

Get Social!

ESXi does not provide an option to backup a running virtual machine, without paying VMware a substantial amount of money. You can get round this by turning off the guest and copying the VMDK however this requires downtime for the guest. You cannot copy the VMDK while the guest is running because the VMDK virtual disk cannot be copied while it is in use. As this is likely to be the boot disk for the virtual machine, stopping disk activity without turning the instance off is impossible. The below simple script creates a snapshot of the guest which forces the guest to write all new changes to a new file instead of writing them to the virtual disk. This frees the disk to be copied. Once the copy has completed, the snapshot is removed writing all changes since the backup started back to the virtual disk.

This script contains little error checking and requires a few conditions to be met in order to complete successfully.
• No device maps for physical disks must exist in the instance
• ‘Independent’ disks must not exist in the instance
• The parameters of the script must be completed correctly.

There are 2 lines in the script which must be configured. Open the script using a text editor and change the below variables to match your preferences.
#Config
BASE_PATH=”PATH_TO_VIRTUAL_MACHINES”
BACKUP_ROOT=”PATH_TO_SAVE_BACKUP”

Example
#Config
BASE_PATH=”/vmfs/volumes/datastore1/Machines/”
BACKUP_ROOT=”/vmfs/volumes/datastore1/Backup/”

Copy the script to the below location on your ESXi server. The file name of the script should be VMbackupBash E.G. /usr/bin/VMbackupBash

To run the script, type
VMbackupBash [MACHINE_FOLDER_TO_BACKUP]
The machine name must be the name of the folder in BASE_PATH which contains the instance to backup.

#!/bin/bash
#Backup VMware instance

echo ""
echo "-------------------------------"
echo "- VM Backup Script -"
echo "- James Coyle -"
echo "-------------------------------"
echo ""

#Config
#root path to where your running instances are stored.
BASE_PATH="/vmfs/volumes/datastore1/Machines/"

#root path to where you would like to save the backup
BACKUP_ROOT="/vmfs/volumes/datastore1/Backup/"

#Do not edit
if [ "$1" ]; then
MACHINE=$1

else
#MACHINE=$1
echo "Enter machine name: "
read MACHINE

fi

BACKUP_APPEND=$(date +"%Y%m%d-%H%M%S")
MACHINE_PATH="$BASE_PATH$MACHINE/"
BACKUP_PATH="$BACKUP_ROOT$MACHINE$BACKUP_APPEND/"

if [ -d $MACHINE_PATH ] && [ -d $BACKUP_ROOT ]; then

cd $MACHINE_PATH

VIMID=`vim-cmd vmsvc/getallvms | egrep -o "[0-9]+[ ]+$MACHINE" | cut -d" " -f1`

if [ -z VIMID ]; then
echo "Could not get VM ID."
vim-cmd vmsvc/getallvms

echo ""
echo "Enter vimid of $MACHINE"
read VIMID
echo ""
echo ""

fi

#Get existing files
FILE_ARRAY=`find $MACHINE_PATH -type f`

I=0
for T in $FILE_ARRAY[@]
do
#echo "$I[$T]"
I=$((I+1))
done

echo "- Backup info"
echo "-------------------------------"
echo " Machine path: $MACHINE_PATH"
echo " Backup path: $BACKUP_PATH"
echo " Using VM ID: $VIMID."
echo " Machine name: $MACHINE."
echo " Files in Machine folder: $I."
echo ""

echo "- Starting backup"
echo "-------------------------------"
mkdir $BACKUP_PATH

echo " Creating snapshot..."
vim-cmd vmsvc/snapshot.create $VIMID tempbackupsnapshot
echo " Snapshot complete."
IFS='
'
for A in $FILE_ARRAY
do
if [ -n "`echo \"$A\" | egrep '.vmdk|.nvram|.vmx'`" ] ; then
FILESIZE=$(stat -c%s "$A")
echo " Copying file: $A - Size: $FILESIZE bytes"
cp "$A" "$BACKUP_PATH"

else
echo " Skipping file: $A"

fi

done

#Remove snapshot
echo " Removing snapshot..."
vim-cmd vmsvc/snapshot.removeall $VIMID
echo " Snapshot removed."

echo " Starting compression..."
tar -czpf "$BACKUP_ROOT/$MACHINE-$BACKUP_APPEND.tgz" "$BACKUP_PATH"
echo " Compression complete."

echo " Removing backup temp..."
rm -rf "$BACKUP_PATH"
echo " Removed temp files."

echo ""
echo "-------------------------------"
echo " Backup Complete!"
echo "-------------------------------"

else
echo ""
echo ""
echo "-------------------------------"
echo " Error"
echo "-------------------------------"
echo " Folder $MACHINE_PATH or $BACKUP_ROOT does not exists"
#exit 1
fi


20 Comments

Janov

2-Dec-2013 at 3:01 am

Hi James,

Thanks for the script. However it does not really work on a pure ESXi 5.1 console. I have to do some modification to make it work.

#!/bin/sh
#Backup VMware instance
# This script is modified by Janov Nguyen on Dec 2nd 2013, tested OK on ESXi 5.1.

echo ""
echo "-------------------------------"
echo "- VM Backup Script -"
echo "- James Coyle -"
echo "-------------------------------"
echo ""

#Config
#root path to where your running instances are stored.
BASE_PATH="/vmfs/volumes/datastore1/"

#root path to where you would like to save the backup
BACKUP_ROOT="/vmfs/volumes/datastore1/Backup/"

#Do not edit
if [ "$1" ]; then
MACHINE=$1

else
#MACHINE=$1
echo "Enter machine name: "
read MACHINE

fi

BACKUP_APPEND=$(date +"%Y%m%d-%H%M%S")
MACHINE_PATH="$BASE_PATH$MACHINE/"
BACKUP_PATH="$BACKUP_ROOT$MACHINE$BACKUP_APPEND/"

if [ -d $MACHINE_PATH ] && [ -d $BACKUP_ROOT ]; then

cd $MACHINE_PATH

VIMID=`vim-cmd vmsvc/getallvms | egrep -o "[0-9]+[ ]+$MACHINE" | cut -d" " -f1`

if [ -z VIMID ]; then
echo "Could not get VM ID."
vim-cmd vmsvc/getallvms

echo ""
echo "Enter vimid of $MACHINE"
read VIMID
echo ""
echo ""

fi

#Get existing files
FILE_ARRAY=`find $MACHINE_PATH -type f`

I=0
for T in $FILE_ARRAY[@]
do
#echo "$I[$T]"
I=$((I+1))
done

echo "- Backup info"
echo "-------------------------------"
echo " Machine path: $MACHINE_PATH"
echo " Backup path: $BACKUP_PATH"
echo " Using VM ID: $VIMID."
echo " Machine name: $MACHINE."
echo " Files in Machine folder: $I."
echo ""

echo "- Starting backup"
echo "-------------------------------"
mkdir $BACKUP_PATH

echo " Creating snapshot..."
vim-cmd vmsvc/snapshot.create $VIMID tempbackupsnapshot
echo " Snapshot complete."
IFS='
'
for A in $FILE_ARRAY
do
if [ -n "`echo \"$A\" | egrep '.vmdk|.nvram|.vmx'`" ] ; then
FILESIZE=$(stat -c%s "$A")
echo " Copying file: $A - Size: $FILESIZE bytes"
cp "$A" "$BACKUP_PATH"

else
echo " Skipping file: $A"

fi

done

#Remove snapshot
echo " Removing snapshot..."
vim-cmd vmsvc/snapshot.removeall $VIMID
echo " Snapshot removed."

echo " Starting compression..."
tar -czpf "$BACKUP_ROOT/$MACHINE-$BACKUP_APPEND.tgz" "$BACKUP_PATH"
echo " Compression complete."

echo " Removing backup temp..."
rm -rf "$BACKUP_PATH"
echo " Removed temp files."

echo ""
echo "-------------------------------"
echo " Backup Complete!"
echo "-------------------------------"

else
echo ""
echo ""
echo "-------------------------------"
echo " Error"
echo "-------------------------------"
echo " Folder $MACHINE_PATH or $BACKUP_ROOT does not exists"
#exit 1
fi

james.coyle

2-Dec-2013 at 6:45 pm

Hi Janov, thanks for the comment.

I have updated the script – it looks like some of the characters were changed or missed when I copied and pasted it from my notes.

Thanks for your feedback :)

Mica Murici

28-Jan-2014 at 2:14 pm

Is this only for ESXi 5 or can be used also on ESXi 4.1.0? Thanx

    james.coyle

    28-Jan-2014 at 5:05 pm

    This works on 4.1 and up.

Mica Murici

29-Jan-2014 at 9:00 am

Thank you for answer. Yes, it works, but i was getting errors like:
> Reason: The system cannot find the file specified.
> Cannot open the disk ‘GW-000001.vmdk’ or one of the snapshot disks it depends on.
> VMware ESX cannot find the virtual disk “GW-000001.vmdk”. Verify the path is valid and try again.

After i manualy modify their vmx file, VM starts without problem, so i can say that it work, great :)

    james.coyle

    29-Jan-2014 at 9:12 am

    I’m glad you got it working :)

wixdb

23-Feb-2014 at 3:58 am

The script requires you to manually modify the vmx file to overcome the vdk prompts.

Had some problems initially but later I was able to get things working. Nice script and thanks for sharing.

Mica Murici

21-Mar-2014 at 12:37 pm

Me again :) Scruipt works flawlessly until reboot. I rebooted machine last week and today i figure it out, that last backup was not done and after checkimg the script, there was no file in the /usr/bin/. Is there any special config needed or script must be installed after every reboot? Thank you!

    james.coyle

    21-Mar-2014 at 1:37 pm

    I don’t believe so – it should be persistent.

Mica Murici

21-Mar-2014 at 2:08 pm

Nevermind, i already fix it via rc.local
Stupid me :)))

Mica Murici

21-Mar-2014 at 2:13 pm

I’m not kidding you. I save the script as /usr/bin/VMbackupBash and after reboot, it was gone. Now i fix it via /etc/rc.local with copying the script from my VMSTORE to /usr/bin and also set cront at that time & now all is working as it should :) Thank you for script anyway :)

Asker

8-Apr-2014 at 6:12 am

Hi,

Our ESXi is currently configured to run with ghettoVCB but recently due a disk failure I came across problems that the VM’s are now saying to consolidate. Because of this, some VM’s aren’t backing up now as it gives an error. Looking at your script, it takes all available VM’s under the specified path. Is there a way where we can only backup selected VMs??

Thank you,
Asker M

    james.coyle

    8-Apr-2014 at 8:33 am

    Hi,

    This script only backs up one VM at a time – so you would therefore specify the VM you would like to backup and let the script do the rest.

Vpatel

15-Aug-2014 at 3:55 am

Does this script work if Raw Disk Map to VM ? I have few Virtual Storage which are using Direct Disk Mapping ( Pass through HBA card ). At the monument I do turnoff VM than copy VM.

    james.coyle

    15-Aug-2014 at 8:53 am

    No, as per the first bullet point.

Vpatel

18-Aug-2014 at 1:25 am

Thanks For your reply . Script working fine for me. End of the script create tar and Creating tar taking Long time . so I am thinking to eliminate that section. Can I delete
only this section.
echo ” Starting compression…”
tar -czpf “$BACKUP_ROOT/$MACHINE-$BACKUP_APPEND.tgz” “$BACKUP_PATH”
echo ” Compression complete.”

Also What need to edit in VMX file ? I haven’t try to boot VM from backup files. I assume VMDK path need to correct.

Richard Inskip

4-Sep-2015 at 10:29 am

Hi

I have modified this a little further as part of one of my blog posts along with how to use this script to rsync virtual machines to a backup server. Hope you dont mind

http://www.realitytech.co.uk/rich/?p=140

    james.coyle

    4-Sep-2015 at 2:09 pm

    That’s great! Anything to make it easier! I’d appreciate if you could keep a reference to my site, but at the end of the day the script is there for people to use and change to suit their needs :)

Craig

14-Nov-2015 at 8:03 pm

In your script you have BASE_PATH=”/vmfs/volumes/datastore1/Machines/”. My VM directories are all located under “/vmfs/volumes/datastore1/”. How did you create (or move) your VMs into the “Machines” subdirectory?

Greg

23-Feb-2018 at 7:25 pm

Hi All,

Here’s a modification made to the original code that allows for variable virtual machine datastores as well as printing the start and end times of the backups.

#!/bin/sh
#Backup VMware instance

echo “”
echo “——————————-”
echo “- VM Backup Script -”
echo “- James Coyle -”
echo “——————————-”
echo “”
a=`date`
echo “Backup Started: $a”

#Config
#root path to where your running instances are stored.
BASE_PATH=`ls -l /vmfs/volumes/$2 | awk -F ‘-> ‘ ‘{print “/vmfs/volumes/”$2″/”}’`

#root path to where you would like to save the backup
BACKUP_ROOT=”/vmfs/volumes/14bec277-06ec60c4/”

#Do not edit
if [ “$1” ]; then
MACHINE=$1

else
#MACHINE=$1
echo “Enter machine name: ”
read MACHINE

fi

BACKUP_APPEND=$(date +”%Y%m%d-%H%M%S”)
MACHINE_PATH=”$BASE_PATH$MACHINE/”
BACKUP_PATH=”$BACKUP_ROOT$MACHINE$BACKUP_APPEND/”

if [ -d $MACHINE_PATH ] && [ -d $BACKUP_ROOT ]; then

cd $MACHINE_PATH

VIMID=`vim-cmd vmsvc/getallvms | egrep -o “[0-9]+[ ]+$MACHINE” | cut -d” ” -f1`

if [ -z VIMID ]; then
echo “Could not get VM ID.”
vim-cmd vmsvc/getallvms

echo “”
echo “Enter vimid of $MACHINE”
read VIMID
echo “”
echo “”

fi

#Get existing files
FILE_ARRAY=`find $MACHINE_PATH -type f | grep -v vswp | grep -v lck`

I=0
for T in $FILE_ARRAY[@]
do
#echo “$I[$T]”
I=$((I+1))
done

echo “- Backup info”
echo “——————————-”
echo ” Machine path: $MACHINE_PATH”
echo ” Backup path: $BACKUP_PATH”
echo ” Using VM ID: $VIMID.”
echo ” Machine name: $MACHINE.”
echo ” Files in Machine folder: $I.”
echo “”

echo “- Starting backup”
echo “——————————-”
mkdir $BACKUP_PATH

echo ” Creating snapshot…”
vim-cmd vmsvc/snapshot.create $VIMID tempbackupsnapshot
echo ” Snapshot complete.”
IFS=’

for A in $FILE_ARRAY
do
if [ -n “`echo \”$A\” | egrep ‘.vmdk|.nvram|.vmx’`” ] ; then
FILESIZE=$(stat -c%s “$A”)
echo ” Copying file: $A – Size: $FILESIZE bytes”
cp “$A” “$BACKUP_PATH”

else
echo ” Skipping file: $A”

fi

done

#Remove snapshot
echo ” Removing snapshot…”
vim-cmd vmsvc/snapshot.removeall $VIMID
echo ” Snapshot removed.”

#echo ” Starting compression…”
#tar -czpf “$BACKUP_ROOT/$MACHINE-$BACKUP_APPEND.tgz” “$BACKUP_PATH”
#echo ” Compression complete.”

#echo ” Removing backup temp…”
#rm -rf “$BACKUP_PATH”
#echo ” Removed temp files.”

a=`date`
echo “Backup Completed: $a”
echo “”
echo “——————————-”
echo ” Backup Complete!”
echo “——————————-”

else
echo “”
echo “”
echo “——————————-”
echo ” Error”
echo “——————————-”
echo ” Folder $MACHINE_PATH or $BACKUP_ROOT does not exists”
#exit 1
fi

Leave a Reply

Visit our advertisers

Quick Poll

How many Proxmox servers do you work with?

Visit our advertisers