#!/bin/bash # # This is a dump script from "info tar" # with lots of modifications. # # Lots of help from info bash and from the web pages # http://www.student.nada.kth.se/~d96-jja/bash/bashtut.html # http://www.gnu.org/manual/bash/html_mono/bashref.html # Warning! \ then space at the end of a line causes no end of problems # # example recovery (done as root): # # cd /backup # tar zxvf dump0.tgz --listed-incremental dump0.inc home/bvds # tar zxvf dump1.tgz --listed-incremental dump1.inc home/bvds # tar zxvf dump2.tgz --listed-incremental dump2.inc home/bvds # # # Files to back up # files="/home /etc /usr/local" # # Directory to put backups in # mntdir="/mnt/jephthah" dir="/mnt/jephthah/backup" # # Backup rate (seconds) # This allows the script to be called at a more # frequent rate than the desired backup rate. # updaterate=$((3600*24)) # # If the machine with the backup directory has # been rebooted, then the nfs volume becomes readonly. # mount $mntdir # # file with number of backups performed on top of # current level 0 dump. # countfile="${dir}/dump.cnt" # # notifysendexists(){ command -v notify-send > /dev/null; } # # Determine if there is a currently running dump # if [ -e ${dir}/in-progress ]; then PID=`cat ${dir}/in-progress` if ps -p ${PID} > /dev/null then echo "Previous backup still running, PID=${PID}, exiting." exit 0 fi fi # # Count number of dumps and find level # if [ $# -eq 0 ]; then if [ -e $countfile ]; then # Test if last update is too recent age=$(($(date +%s) - $(stat $countfile -c %Y))) if [ $age -lt $updaterate ]; then echo "Last update $age seconds ago, exiting." umount $mntdir exit 0 fi count=$(( $(cat $countfile) + 1 )) level=0 j=$count until [ $j -eq 0 ]; do level=$(( $level+(j&1) )) j=$(( j>>1 )) # echo "In loop, level is $level." done else echo "Can't find file $countfile, exiting." exit 666 fi else level=$1 count=$(( (1<<$level) -1 )) fi # echo "Starting level $level dump, dump number $count" notifysendexists && notify-send "Disk backup" "Starting level $level dump, dump number $count." -u normal # # Move older copies to backup directory # This moves all files at the present level and higher # if [ ! -d ${dir}/backback ]; then mkdir ${dir}/backback; fi if [ ! -d ${dir}/back ]; then mkdir ${dir}/back; fi # # Don't move files if last attempt was not completed. i=$level while [ -e ${dir}/dump${i}.tgz ] && [ ! -e ${dir}/in-progress ]; do if [ -e ${dir}/back/dump${i}.tgz ]; then mv ${dir}/back/dump${i}.* ${dir}/backback echo " moving ${dir}/back/dump${i}.* to ${dir}/backback" fi mv ${dir}/dump${i}.* ${dir}/back echo " moving ${dir}/dump${i}.* to ${dir}/back" i=$(( i+1 )) done # # # For dump levels higher than zero, find previous # snapshot file and copy it. # if [ $level -ne 0 ]; then datfile=${dir}/dump$(( $level -1 )).inc if [ -e $datfile ]; then cp $datfile ${dir}/dump${level}.inc else echo "Snapshot file $datfile doesn't exist, exiting." exit 1 fi fi # # Handle case where backup is interrupted. echo "$$" > ${dir}/in-progress # # perform tar using snapshot file # # turned off verbose -v # Exit on failed write, allow failed read. # if tar --ignore-failed-read -z -c \ -f ${dir}/dump${level}.tgz\ --label="User dump on date $(date)"\ --listed-incremental=$dir/dump${level}.inc\ ${files} then # # save count in count file # rm ${dir}/in-progress echo $count > $countfile echo " backup completed." notifysendexists && notify-send "Disk backup" "Backup completed" -u normal else echo " backup failed, error ${ERRCODE}, exiting" notifysendexists && notify-send "Disk backup" "Backup failed" -u normal exit $ERRCODE fi # # We don't want users to read the dump files # chmod 600 ${dir}/dump${level}.tgz chmod 600 ${dir}/dump${level}.inc # umount $mntdir #