I got the skeleton of this script from another post.
DISCLAIMER: Use this at your own risk. I am not responsible for any data corruption or loss that may occur if you decide to use this without first making sure it works for you.
After playing around with it for hours I have made some changes:
- When called without arguments show a list of backup candidates
- Validate the VMID
- Make sure all VM files are copied even if a VM is stored on multiple data stores
- Work around some weird ash bugs I discovered while testing
To use copy this file to /sbin/vmbackup.sh on ESXi box and make it executeable.
You need to change the BACKUPHOST, BACKUPUSER and BACKUPPW values to suit and copy it in scp mode because the ESXi box doesn't have a sftp server on the SSH console.
#!/bin/sh VERSION=2.0 if [ -z "$1" ]; then echo "Usage: $0 vmid" echo "Your choices are:" vim-cmd /vmsvc/getallvms | grep -v "Name" | awk -F"[" '{ print $1 }' exit 1 fi SERVNAME=$1 # Backup host information BACKUPHOST=10.11.12.13 BACKUPUSER=ftpuser BACKUPPW='ftppassword' # you must create the backup target # if vmname is "WinXP Pro Client" then # make a dir on the remote ftp server under BACKUPDIR with that name # ftpput will not do it for you # e.g. mkdir "/media/disk/backup/WinXP Pro Client" BACKUPDIR='/media/disk/backup' # Get vm info #VMID=`echo $1 /vmsvc/getallvms | grep -v "^Vmid" | grep "$SERVNAME" | awk '{ print $1 }'` # Using the passed in VMID check if it's valid and exit if not VMID=`vim-cmd /vmsvc/getallvms | grep -v "Name" | awk '{ print $1 }' | grep -E "^$1$"` if [ -z "$VMID" ]; then echo Invalid VM ID exit 1 fi VMNAME=`vim-cmd /vmsvc/getallvms | grep -i "^$VMID " | awk -F" {2,}" '{ print $2 }'` # awk -F" {2,}" '{ print $2 }' VMSTAT=`vim-cmd /vmsvc/power.getstate $VMID | grep Powered | awk '{ print $2 }'` # vms can exist on multiple data stores so... # grab the entire url line # e.g. # url /vmfs/volumes/4c372585-c5be3670-5b7e-001d091edb9f /vmfs/volumes/4c371e81-0c463360-dfe3-001d091edb9f VMDATASTORES=`vim-cmd /vmsvc/get.datastores $VMID | grep url` # this is better but untested (doens't capture the url first token) # comment out the "if [ "$j" != "url" ] ; then" if statement # line if you use this #VMDATASTORES=`vim-cmd /vmsvc/get.datastores $VMID | grep url | awk '{$1=""; print $0}'` echo "Datastores for $VMID" echo $VMDATASTORES #echo At the end #exit 1 # vmname can be wildly different from vmdir so find vmdir VMDIR=`vim-cmd /vmsvc/getallvms | grep -i "^$VMID " | awk -F"[]/]" '{ print $2 }' | sed 's/^[[:space:]]*\(.*\)[[:space:]]*$/\1/'` # get the power status (is it on or off) VMSTAT=`vim-cmd /vmsvc/power.getstate $VMID | grep Powered | awk '{ print $2 }'` if [ "$VMSTAT" = "off" ]; then echo "Server $VMNAME with VMID $VMID is already powered off" else echo "Powering off server $VMNAME with ID $j" vim-cmd /vmsvc/power.shutdown $VMID VMSTAT=on echo "Checking status (now $VMSTAT)" while [ "$VMSTAT" = "on" ]; do echo wait for "$VMNAME" to shutdown.. sleep 10 VMSTAT=`vim-cmd /vmsvc/power.getstate $VMID | grep Powered | awk '{ print $2 }'` done # ensure to start vm again when it was running: VMSTAT=on fi # set the field separator to new line because it doesn't like # spaces in the names # IFS=$(echo -e '\n') # or you can use #IFS=' #' # working around ash bug regarding spaces in files # echo Ok succesfully changed dir for j in $VMDATASTORES do # vmlocation is the vmdatastore and vmdir if [ "$j" != "url" ] ; then VMLOCATE="$j/$VMDIR" echo "Location: $VMLOCATE" echo change to vmware dir cd "$VMLOCATE" || exit 1 for i in ./*; do FILE=`echo $i | sed s+\./++` echo backup "$VMLOCATE/$FILE" to "$BACKUPDIR/$VMNAME/$FILE" on $BACKUPHOST ftpput -u $BACKUPUSER -p $BACKUPPW $BACKUPHOST "$BACKUPDIR/$VMNAME/$FILE" "$FILE" done fi done if [ "$VMSTAT" = "on" ]; then # vm was on when we started the backup, now start it again vim-cmd /vmsvc/power.on $VMID fi
0 Comments