Cold Backup Script

cold_backup.sh
#!/bin/bash

# https://github.com/vacri/operations/blob/master/kvm-backup
# This script shuts down virtual guests (it's helpful for Windows guests to have the qemu-agent + virtio serial device and drive installed + channel qemu-ga; this ensures proper shutdown).
# This version of the script uses pigz for compression and mbuffer to buffer...
# Install pigz via "yum install pigz" and enable the EPEL repo to install mbuffer "yum install epel-release" then "yum install mbuffer"
# yum install epel-release && yum install pigz mbuffer tar
# This is who we'll back up
#
machines="DMS-ACCESS-PA"

#
# Keep the house clean
#
days_to_keep="6"

#
# Store backups here. NFS to another machine would make sense. 
# so that your backups are not local.
#
backup_dir="/mnt/172.18.18.30/VG_BACKUPS/VHSRV01"

#
# Logs go here.
#
log_dir="/mnt/172.18.18.30/VG_BACKUPS/VHSRV01/logs"

#
# End parameters
#
#=================================================================

#
# Timestamp for the log file
#
right_now=`date '+%m%d%Y_%H%M%p'`

exec 1>/${log_dir}/backup_vms.${right_now}.log 2>&1

print_date() {
   date '+%m%d%Y_%H%M%p'
}

for machine in $machines
do
   if [[ ! -d ${backup_dir}/${machine} ]];
   then
      mkdir -p ${backup_dir}/${machine}
   fi

   echo "Backing up VM configuration"
   virsh dumpxml $machine > ${backup_dir}/${machine}/${machine}.xml

   echo "Sending shutdown signal to $machine"
   virsh shutdown --mode=agent $machine 
   virsh shutdown $machine
   echo "   Return code: $?"
   
   echo -n "Waiting for machine to shut down "
   sleep 120
   for i in 1 2 3 4 5
   do
      echo -n "."

# Note, grep -v "BACKUP" is used to exclude any disk images that backup in their name, use as needed.

      virsh list | grep -v "^$" | grep -v "^ Id" | grep -v "\-\-\-\-\-" | awk '{print $2" "$3}' | grep $machine | while read name state
      do
         if [[ $state -eq "running" ]]
         then
            sleep 600
         fi
      done
   done

   echo "Copying disk(s)"
   virsh domblklist $machine | grep -v "^$" | grep -v "^Target" | grep -v "\-\-\-\-\-" | grep -v "BACKUP" | awk '{print $2}' | while read disk
   do
      echo "   $disk ..."
      copy_disk="${backup_dir}/${machine}/`basename ${disk}`.tar.gz.`print_date`"
      echo "   Copying $disk to $copy_disk"
      fuser $disk 1>/dev/null 2>&1
      if (( $? == 0 ))
      then
         echo "   Disk $disk is still in use! "
      else
         echo "   Copy started at `print_date`"
#         cp $disk $copy_disk
	   tar -c $disk | mbuffer | pigz -1 | mbuffer > $copy_disk
         echo "   Return code: $?"
         echo "   Copy ended at `print_date`"
#         echo "   Backgrounding bzip of $copy_disk"
#         nohup bzip2 $copy_disk &
      fi
   done

   echo "Starting machine $machine"
   virsh start $machine
   echo "   Return code: $?"
   echo

done

#   echo "Removing old backups."
   find $backup_dir -type f -mtime +$days_to_keep -ls
   find $backup_dir -type f -mtime +$days_to_keep -exec rm -f {} \;

Cold Backup Crontab Example

As root do crontab -e then add (modify path/names as needed):

#m(0-59) h(0-23) dom(1-31) m(1-12) dow(0 is Sunday) command
0 3 * * 4 /root/cold_backups.sh