Incrimental Backups
Here is a bash script to do incrimental backups via ssh and rsync.
- !/bin/bash
#do the usage or help section #default port if none given
getopt --test > /dev/null if $? -ne 4 ; then echo "I’m sorry, `getopt --test` failed in this environment." exit 1 fi
OPTIONS=hdwmtvp:rl: LONGOPTIONS=hourly,daily,weekly,monthly,test,verbose,port:,rsyncskip,login:
# -temporarily store output to be able to check for errors # -e.g. use “--options” parameter by name to activate quoting/enhanced mode # -pass arguments only via -- "$@" to separate them correctly PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTIONS --name "$0" -- "$@") if $? -ne 0 ; then # e.g. $? == 1 # then getopt has complained about wrong arguments to stdout echo "This is an incrimental backup system designed to make backups from remote systems to the local system" echo "You can also make backups from the local system to the local system" echo "This script is designed to be run as a cronjob and normally will provide no output" echo "Since this script is run as a cronjob and uses ssh to connect to remote servers, you must use ssh-keys to avoid password prompts" echo echo "USAGE: ./testscript [options] <source> <destination>" echo "The options are:" echo "-h or --hourly for preforming hourly incrimental backups" echo "-d or --daily for preforming daily incrimental backups" echo "-w or --weekly for preforming weekly incrimental backups" echo "-m or --monthly for preforming monthly incrimental backups" echo "-t or --test for test mode. The program will run through the process of prefroming a backup without actually makeing any real changes" echo "-v or --verbose adds output for testing purposes" echo "-l or --login <someuser@1.2.3.4> used to specify your username and the ip address of the remote server" echo "-p or --port <1234> used to specify the remote servers port to connect to. The default is 22" echo "-r or rsyncskip used to skip the rsync dry-run command if your trying to see whats going on with -v or --verbose and rsync is filling up your scroll buffer" exit 2 fi # read getopt’s output this way to handle the quoting right: eval set -- "$PARSED"
# now enjoy the options in order and nicely split until we see -- while true; do case "$1" in -h|--hourly)
MODE=HOURLY
shift
;;
-d|--daily)
MODE=DAILY shift
;;
-w|--weekly) MODE=WEEKLY shift ;; -m|--monthly) MODE=MONTHLY shift ;; -t|--test) TESTRUN=YES shift ;;
-v|--verbose)
VERBOSE=YES shift ;; -p|--port) PORT="-p $2"; shift 2;;
-l|--login) LOGIN="$2"; shift 2;;
-r|--rsyncskip) RSYNCSKIP=YES shift;;
-H|--help) echo "This is an incrimental backup system designed to make backups from remote systems to the local system" echo "You can also make backups from the local system to the local system" echo "This script is designed to be run as a cronjob and normally will provide no output" echo "Since this script is run as a cronjob and uses ssh to connect to remote servers, you must use ssh-keys to avoid password prompts" echo echo "USAGE: ./testscript [options] <source> <destination>" echo "The options are:" echo "-h or --hourly for preforming hourly incrimental backups" echo "-d or --daily for preforming daily incrimental backups" echo "-w or --weekly for preforming weekly incrimental backups" echo "-m or --monthly for preforming monthly incrimental backups" echo "-t or --test for test mode. The program will run through the process of prefroming a backup without actually makeing any real changes" echo "-v or --verbose adds output for testing purposes" echo "-l or --login <someuser@1.2.3.4> used to specify your username and the ip address of the remote server" echo "-p or --port <1234> used to specify the remote servers port to connect to. The default is 22" echo "-r or rsyncskip used to skip the rsync dry-run command if your trying to see whats going on with -v or --verbose and rsync is filling up your scroll buffer" echo exit 0;
;;
--)
shift break ;;
*)
echo "Programming error"
exit 3 ;; esac done
# handle non-option arguments if $# -ne 2 ; then echo "$0: A single input file is required." exit 4 fi
# test to make sure the source exists and is reachable if [ -n "$LOGIN" ]; then if ! ssh "$PORT" "$LOGIN" ls "$1" >/dev/null 2>&1 ; then
echo "ERROR Target Directory: $2 is unreachable or does not exist" exit 1;
else
SOURCE="$LOGIN:$1"
fi else SOURCE="$1" fi
#check to see if the destination dir exists if [ -d "$2" ]; then TRG="$2" else echo "destination directory doesn't exist." exit 1; fi
# Perform an hourly backup ****should probably make a case statement***** if [ $MODE = HOURLY ]; then
#Today's date: DAY0=`date +%Y_%a_%b_%d_%H` #Today's date minus 25 hours DAY24=`date -d "25 hours ago" +%Y_%a_%b_%d_%H` #One hour ago: DAY1=`date -d "1 hour ago" +%Y_%a_%b_%d_%H`
#The target directory: TRG+=$DAY0
#The Link Dir LNKDIR="/media/4USB/backup/sserver/$DAY1/"
if [ -d "$LNKDIR" ]; then LNK="--link-dest=$LNKDIR" else LNK="" fi
#Set rsync run options if $TESTRUN = YES ; then if $VERBOSE = YES ; then #Verbose + Test Mode OPT="-ahvn --delete" echo "Hourly Mode: Verbose + Test Mode" echo else #Quite + Test Mode OPT="-ahqn --delete" fi else if $VERBOSE = YES ; then #Verbose + Real Run OPT="-ahv --delete" echo "Hourly Mode: Verbose + Real Run" echo else #Quiet + Real Run OPT="-ahq --delete" fi fi
if $VERBOSE = YES ; then
echo "This script will backup files from:" echo "$SOURCE" echo echo "To:" echo "$TRG" echo if [ -d "$LNKDIR" ]; then echo "The files in: $SOURCE that match the files in" echo "$LNKDIR will be symbolicly linked instead of copied" else echo "This must be the first time a backup of this type has" echo "been made because the link directory: $LNKDIR does not exist" fi echo echo "The rsync command that will be used is:" echo "rsync "$OPT $LNK -e "'ssh -p 2222'" $SRC $TRG echo
fi
#Execute the backup if $RSYNCSKIP != "YES" ; then rsync $OPT $LNK -e 'ssh -p 2222' $SOURCE $TRG fi
#Delete the backup from 25 hours ago, if it exists if $VERBOSE = YES ; then if [ -d /media/4USB/backup/sserver/$DAY24 ]; then echo "Old backup found." echo if $TESTRUN = YES ; then echo "simulatingdeleting old backup:" echo "rm -Rf /media/4USB/backup/sserver/$DAY24" fi else echo "Old backup from 25 hours ago NOT found" echo fi else if [ -d /media/4USB/backup/sserver/$DAY24 ]; then if $TESTRUN != YES ; then rm -Rf /media/4USB/backup/sserver/$DAY24 fi fi fi
elif [ $MODE = DAILY ]; then #Today's date: DATE_TODAY=`date +%Y_%a_%b_%d`
#The date at last midnight******maybe check and see if it exists if not then error out***** DATE_LAST_MIDNIGHT=`date -d "1 day ago" +%Y_%a_%b_%d_00` #DATE_8_DAYS_AGO DATE_8_DAYS_AGO=`date -d "8 days ago" +%Y_%a_%b_%d`
#The target directory: TRG+=$DAY0
#The Link Dir LNKDIR="/media/4USB/backup/sserver/$DATE_LAST_MIDNIGHT/"
if [ -d "$LNKDIR" ]; then LNK="--link-dest=$LNKDIR" else LNK="" fi
#Set rsync run options if $TESTRUN = YES ; then
if $VERBOSE = YES ; then #Verbose + Test Mode OPT="-ahvn --delete" echo "Daily Mode: Verbose + Test Mode" echo else #Quite + Test Mode OPT="-ahqn --delete" fi
else
if $VERBOSE = YES ; then #Verbose + Real Run OPT="-ahv --delete" echo "Daily Mode: Verbose + Real Run" echo else #Quiet + Real Run OPT="-ahq --delete" fi
fi
if $VERBOSE = YES ; then echo "This script will backup files from:" echo "$SOURCE" echo echo "To:" echo "$TRG" echo if [ -d "$LNKDIR" ]; then echo "The files in: $SOURCE that match the files in" echo "$LNKDIR will be symbolicly linked instead of copied" else echo "This must be the first time a backup of this type has" echo "been made because the link directory: $LNKDIR does not exist" fi echo echo "The rsync command that will be used is:" echo "rsync "$OPT $LNK -e "'ssh -p 2222'" $SRC $TRG echo fi
#Execute the backup
if $RSYNCSKIP != "YES" ; then rsync $OPT $LNK -e 'ssh -p 2222' $SOURCE $TRG fi
#Delete the backup from 8 days ago, if it exists if $VERBOSE = YES ; then if [ -d /media/4USB/backup/sserver/$DATE_8_DAYS_AGO ]; then echo "Old backup found." echo if $TESTRUN = YES ; then echo "simulatingdeleting old backup:" echo "rm -Rf /media/4USB/backup/sserver/$DATE_8_DAYS_AGO" fi else echo "Old backup from 8 days ago NOT found" echo fi else if [ -d /media/4USB/backup/sserver/$DATE_8_DAYS_AGO ]; then if $TESTRUN != YES ; then rm -Rf /media/4USB/backup/sserver/$DATE_8_DAYS_AGO fi fi fi
#Weekly backup. Saves 4 weeks worth of backups. elif [ $MODE = WEEKLY ]; then #Today's week number: DATE_THIS_WEEK=`date +%Y_Week_%U`
#Today's date:
DATE_TODAY=`date +%Y_%a_%b_%d`
#Date one week ago DATE_5_WEEKS_AGO=`date -d "5 weeks ago" +%Y_Week_%U`
#The target directory: TRG+=$DAY0 #The Link Dir LNKDIR="/media/4USB/backup/sserver/$DATE_5_WEEKS_AGO/"
#Check and see if the link directory exists. if not then don't use the rsync --link-dest option if [ -d "$LNKDIR" ]; then LNK="--link-dest=$LNKDIR" else LNK="" fi
#Set rsync run options if $TESTRUN = YES ; then if $VERBOSE = YES ; then #Verbose + Test Mode OPT="-ahvn --delete" echo "Weekly Mode: Verbose + Test Mode" echo else #Quite + Test Mode OPT="-ahqn --delete" fi else if $VERBOSE = YES ; then #Verbose + Real Run OPT="-ahv --delete" echo "Weekly Mode: Verbose + Real Run" echo else #Quiet + Real Run OPT="-ahq --delete" fi fi
if $VERBOSE = YES ; then echo "This script will backup files from:"
echo "$SOURCE" echo echo "To:" echo "$TRG" echo if [ -d "$LNKDIR" ]; then echo "The files in: $SOURCE that match the files in" echo "$LNKDIR will be symbolicly linked instead of copied" else echo "This must be the first time a backup of this type has" echo "been made because the link directory: $LNKDIR does not exist" fi echo
echo "The rsync command that will be used is:" echo "rsync "$OPT $LNK -e "'ssh -p 2222'" $SRC $TRG
echo
fi
#Execute the backup if $RSYNCSKIP != "YES" ; then rsync $OPT $LNK -e 'ssh -p 2222' $SOURCE $TRG fi
#Delete the backup from 5 weeks ago, if it exists if $VERBOSE = YES ; then if [ -d /media/4USB/backup/sserver/$DATE_5_WEEKS_AGO ]; then echo "Old backup found." echo if $TESTRUN = YES ; then echo "simulatingdeleting old backup:" echo "rm -Rf /media/4USB/backup/sserver/$DATE_5_WEEKS_AGO" fi else echo "The Old backup from 5 weeks ago was NOT found" echo fi else
if [ -d /media/4USB/backup/sserver/$DATE_5_WEEKS_AGO ]; then if $TESTRUN != YES ; then
rm -Rf /media/4USB/backup/sserver/$DATE_5_WEEKS_AGO fi
fi
fi
#Monthly backup. Saves 12 months worth of backups. elif [ $MODE = MONTHLY ]; then #Today's week number: DATE_THIS_MONTH=`date +%Y_%m` #Today's date: DATE_TODAY=`date +%Y_%a_%b_%d` #Date one week ago DATE_13_MONTHS_AGO=`date -d "13 months ago" +%Y_%m`
#The target directory: TRG+=$DAY0 #The Link Dir LNKDIR="/media/4USB/backup/sserver/$DATE_13_MONTHS_AGO/"
#Check and see if the link directory exists. if not then don't use the rsync --link-dest option if [ -d "$LNKDIR" ]; then LNK="--link-dest=$LNKDIR" else LNK="" fi
#Set rsync run options if $TESTRUN = YES ; then if $VERBOSE = YES ; then #Verbose + Test Mode OPT="-ahvn --delete" echo "Monthly Mode: Verbose + Test Mode" echo else #Quite + Test Mode OPT="-ahqn --delete" fi else if $VERBOSE = YES ; then #Verbose + Real Run OPT="-ahv --delete" echo "Monthly Mode: Verbose + Real Run" echo else #Quiet + Real Run OPT="-ahq --delete" fi fi
if $VERBOSE = YES ; then echo "This script will backup files from:" echo "$SOURCE" echo echo "To:" echo "$TRG" echo if [ -d "$LNKDIR" ]; then echo "The files in: $SOURCE that match the files in" echo "$LNKDIR will be symbolicly linked instead of copied" else echo "This must be the first time a backup of this type has" echo "been made because the link directory: $LNKDIR does not exist" fi echo echo "The rsync command that will be used is:" echo "rsync "$OPT $LNK -e "'ssh -p 2222'" $SRC $TRG echo fi
#Execute the backup if $RSYNCSKIP != "YES" ; then rsync $OPT $LNK -e 'ssh -p 2222' $SOURCE $TRG fi
#Delete the backup from 13 months ago, if it exists if $VERBOSE = YES ; then if [ -d /media/4USB/backup/sserver/$DATE_13_MONTHS_AGO ]; then echo "Old backup found." echo if $TESTRUN = YES ; then echo "simulatingdeleting old backup:" echo "rm -Rf /media/4USB/backup/sserver/$DATE_5_WEEKS_AGO" fi else echo "The Old backup from 13 months ago was NOT found" echo fi else if [ -d /media/4USB/backup/sserver/$DATE_13_MONTHS_AGO ]; then if $TESTRUN != YES ; then rm -Rf /media/4USB/backup/sserver/$DATE_13_MONTHS_AGO fi fi fi fi