#!/bin/bash #https://pastebin.com/URrtG3hP set -e if [ ! -z "$1" ]; then if [ ! -d "/var/log/kvm_backup" ]; then mkdir -vp "/var/log/kvm_backup" | tee -a '/var/log/kvm_backup/'$1'.log' fi echo "" | tee -a '/var/log/kvm_backup/'$1'.log' echo "" | tee -a '/var/log/kvm_backup/'$1'.log' ########################################## #backupdir=''$PWD'/kvm_backup' backupdir='/backup/backup/kvm_backup' keepbackups=4 ########################################## if ! command -v virsh &> /dev/null; then echo "Error: virsh command not found. Please install libvirt-bin package." | tee -a '/var/log/kvm_backup/'$1'.log' exit 1 fi if ! command -v rsync &> /dev/null; then echo "Error: rsync command not found. Please install rsync package." | tee -a '/var/log/kvm_backup/'$1'.log' exit 1 fi if [ ! -d "$backupdir" ]; then echo "Error: Backup directory does not exist." | tee -a '/var/log/kvm_backup/'$1'.log' exit 1 fi datum=`date +"%s-%d-%m-%y"` name="$1" moment=''$name'_'$datum'' running=`virsh list|grep $1|tr -s ' '|cut -d ' ' -f 3` disks=`virsh domblklist "$1" --details|grep qcow2|tr -s ' '|awk '{print $3 "|" $4}'` snapdir=''$backupdir'/'$1'_'$datum'' if [ "$running" == "$1" ]; then if [ ! -d "$backupdir" ]; then mkdir -p "$backupdir" fi if [ -d "$backupdir" ]; then if [ ! -z "$disks" ]; then mkdir -p $snapdir if [ -d "$snapdir" ]; then for disk in $disks; do typ=`echo $disk | cut -d '|' -f 1` file=`echo $disk | cut -d '|' -f 2` base=`basename $file` filename=''$backupdir'/'$1'_'$datum'/'$base'' echo 'INFO: Starting Backup of '$1'_'$datum'' | tee -a '/var/log/kvm_backup/'$1'.log' if [ ! -f "$file" ]; then echo "####################################################################################" | tee -a '/var/log/kvm_backup/'$1'.log' echo "# WARNING: #" | tee -a '/var/log/kvm_backup/'$1'.log' echo "# Source File is deleted. Try Backup from /proc #" | tee -a '/var/log/kvm_backup/'$1'.log' echo "# Need to hard crash (kill -9) the VM and recover the Source File from Backup File #" | tee -a '/var/log/kvm_backup/'$1'.log' echo "####################################################################################" | tee -a '/var/log/kvm_backup/'$1'.log' delid=`lsof -wXT | grep "$base" | grep deleted | head -n 1|tr -s ' '| awk '{print $2}'` olddisk=`ls -l /proc/"$delid"/fd/ | grep "$base"|tr -s ' '| awk '{print $9}'` kill -STOP "$delid" echo "WARN: Backup $1 -> /proc/$delid/fd/$olddisk -> $filename" | tee -a '/var/log/kvm_backup/'$1'.log' if ! dd if="/proc/$delid/fd/$olddisk" of="$filename" bs=1M status=progress; then echo "ERROR: Failed to create Backup of $1." | tee -a '/var/log/kvm_backup/'$1'.log' exit 1 fi kill -CONT "$delid" echo "INFO: Backup "$1" -> /proc/"$delid"/fd/"$olddisk" to "$filename" complete." | tee -a '/var/log/kvm_backup/'$1'.log' else if ! virsh snapshot-create-as --domain $1 --name $moment \ --diskspec $typ,file=''$filename'' \ --disk-only --atomic \ --no-metadata; then echo "ERROR: Failed to create snapshot." | tee -a '/var/log/kvm_backup/'$1'.log' exit 1 fi if ! rsync -avhW --progress --log-file='/var/log/kvm_backup/'$1'.log' ''$file'' ''$backupdir'/'$1'_'$datum'/'; then echo "ERROR: Failed to copy disk image." | tee -a '/var/log/kvm_backup/'$1'.log' exit 1 else virsh blockcommit "$1" "$typ" --wait --active --verbose virsh blockjob "$1" "$filename" --pivot echo "INFO: Backup "$1" -> "$file" to "$backupdir"/"$1"_"$datum" complete." | tee -a '/var/log/kvm_backup/'$1'.log' fi fi done virsh dumpxml "$1" > ''$backupdir'/'$1'_'$datum'/'$1'.xml' networks=$(virsh domiflist "$1" | grep network | tr -s ' ' | awk '{ print $3}') for network in $networks; do virsh net-dumpxml "$network" > ''$backupdir'/'$1'_'$datum'/'$network'.xml' done anz=`ls -d $backupdir/$1*|wc -l` if (( "$anz" > "$keepbackups" )); then cleanfile=`ls -d $backupdir/$1*|sort|head -n 1` if [ ! -z "$cleanfile" ]; then rm -vdR "$cleanfile" fi fi fi fi fi else echo "ERROR: VM not running." fi else echo "ERROR: Missing VM Name." fi