Skip to content

Instantly share code, notes, and snippets.

@jaysn
Last active October 9, 2019 14:07
Show Gist options
  • Save jaysn/c724593f0e98587a7e419a723aaabe8d to your computer and use it in GitHub Desktop.
Save jaysn/c724593f0e98587a7e419a723aaabe8d to your computer and use it in GitHub Desktop.
basic Cron Bash Script to automatically save specific VirtualBox VMs using savestate, copy, tar and p7zip
#!/bin/bash
# Vars
# BUDATE - our date used for the Backup-Folder name which is created in our Backup-Path
# VBOXUSER - used if your VirtualBox is started and managed by a special/specific user
# BACKUPMNT - the mountpoint of your Backup-Media/HDD/SSD/whatever
# VMPATH - Path to your VirtualBox VMs Folder
# BUPATH - complete Path to your Backup-Folder - where date-based folders are created for each (Daily-)Backup
# VMLIST - List of VMs (Names only) to backup - passed to vboxmanage and used for the Copy-Part so please use names only..
BUDATE=`date +%Y-%m-%d`
VBOXUSER=vbox
BACKUPMNT='/mnt/backupdrive'
VMPATH="/path/to/VirtualBox VMs" # edit me to match your path to VirtualBox VMs
BUPATH=${BACKUPMNT}/backup/virtualbox
#Change this list of VMs to match your needs
VM_LIST=("VM-NAME-1" "VM-NAME-2" "USE-ONLY-VM-NAMES")
#this functions can be used to check if a device or path it mounted for example our Backup-Mount
isMounted() { findmnt -rno SOURCE,TARGET "$1" >/dev/null; } # path or device
isDevMounted() { findmnt -rno SOURCE "$1" >/dev/null; } # device only
isPathMounted() { findmnt -rno TARGET "$1" >/dev/null; } # path only
writelog() { /usr/bin/logger -tsave-vms -plocal6.notice $1; } # writes $1 to predefined syslog facility with our save-vms tag
#
#Let the games begin
#
writelog "Starting VM Backup ${BUDATE}" # Log for our Syslog
echo "Starting VM Backup ${BUDATE}" # Output for our Cron-Mail
#
#Mountcheck - Check if our Backup-Space is mounted
#
if ! isPathMounted $BACKUPMNT;
then
writelog "${BACKUPMNT} not mounted! mounting now"
echo "${BACKUPMNT} not mounted! mounting now"
mount ${BACKUPMNT}
fi
writelog "Pausing VMs"
echo "Pausing VMs"
for vm in "${VM_LIST[@]}"
do
writelog "Pausing ${vm}";
echo "Pausing ${vm}";
su -l $VBOXUSER -c "VBoxManage controlvm '${vm}' savestate"
done
unset vm
writelog "all VMs paused"
echo "all VMs paused"
if [ ! -d ${BUPATH}/${BUDATE} ]
then
echo "Make Dir ${BUPATH}/${BUDATE}"
mkdir ${BUPATH}/${BUDATE}
fi
for cvm in "${VM_LIST[@]}"
do
writelog "Copying VM ${cvm}"
echo "Copying VM ${cvm}"
cp -r "${VMPATH}/${cvm}" ${BUPATH}/${BUDATE}/${cvm}
done
unset cvm
for vm in "${VM_LIST[@]}"
do
echo ""
su -l ${VBOXUSER} -c "VBoxManage startvm '${vm}' --type=headless"
done
unset vm
echo "All VMs should be Back online, Start compression of our temporary copies."
for bakdir in ${BUPATH}/${BUDATE}/*/
do
writelog "Compressing ${bakdir}"
tar c "${bakdir}" | 7z a -t7z -m0=lzma2 -mx=5 -si "${bakdir%/}.tar.7z"
done
echo "All backups compressed"
unset bakdir
#removing the copied, uncompressed VM Folders
for vm in "${VM_LIST[@]}"
do
rm -r ${BUPATH}/${BUDATE}/${vm}
done
#
# TODO
#
# delete older backups. using find -not -newermt or find -mtime +7 for a week or sth like this..
#
# find ${BUPATH} -type d -mtime +7 -exec rm -r {}
# or
# find ${BUDATE} -maxdepth 1 -type d -mtime +7 -not -mtime +14
# the -not -mtime condition in my case prevents deletion of backups older than x days
# in my case i have master-copies in the same folder which i need to be untouched ;)
# this could be less specific if you, other than me, use a dedicated folder only for this backups-purpose...
#
# also
#
# Adding a separate temporary working directory and or space for the copies before compressing them and
# copying only the final archives to the backup-space could be better on smaller backup-targets.
# for example u could use /tmp for this.. or another ssd/hdd drive - just check for it using the isMounted functions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment