Backup using rsync

Making a backup is a must. And although doing it manually works, it is far from perfect. What if you are busy one week and can’t run your backup?

And then there is the question about what method to use. Do you go with a commercial solution? Or one of the free alternative systems?
Why not go outside your comfort zone and use a standard tool?

Well that’s what I thought anyway…

Let’s first take a look at the actual script:

#!/bin/bash
###############################################################################
# Script to make a backup of files using rsync.
# It rotates directories automatically.
#
# To ensure the backupdrive is mounted, the script checks for the existance of 
# a file named 'mount_OK' (without the quotes)
#
# Copyright 2014 Rene Rasmussen
#
# Published under the MIT license. 
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy 
# of this software and associated documentation files (the "Software"), 
# to deal in the Software without restriction, including without limitation 
# the rights to use, copy, modify, merge, publish, distribute, sublicense, 
# and/or sell copies of the Software, and to permit persons to whom the 
# Software is furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included 
# in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
# IN THE SOFTWARE.
#
###############################################################################

# Backup drive mountpoint
backup_drive="/mnt/backer"

# Parent backup directory
backup_parent_dir="${backup_drive}/homeback"

# Number of backups
# (number of directories in rotation)
# count starts from 0, so below value defines directories+1
backup_dir_count=12

#initialize errors variable
errors=0

# Check if drive is mounted
# (check for mount_OK file)
okFile=${backup_drive}/mount_OK
if [ -f $okFile ]
then
   # If the destination folder does not exist, it will be created
   if [ ! -d $backup_parent_dir ]
   then
      mkdir -p $backup_parent_dir
      chmod 750 $backup_parent_dir
   fi
   # Rotate backup directories
   for (( c=$backup_dir_count; c>=2; c-- ))
   do
      if [ $c -eq $backup_dir_count ]
      then
         dirPath=${backup_parent_dir}/backup$c
         #echo "0 = $dirPath" #debug
         if [ -d $dirPath ]
         then
            rm -rf $dirPath
         fi
      fi
         dirPath1=${backup_parent_dir}/backup$((c-1))
         dirPath2=${backup_parent_dir}/backup$c
         #echo "1 = $dirPath1" #debug
         #echo "2 = $dirPath2" #debug
         if [ -d $dirPath1 ]
         then
            mv $dirPath1 $dirPath2
         fi
   done
   # copy contents from backup0 to backup1 with hardlinks
   dirPath1=${backup_parent_dir}/backup0
   dirPath2=${backup_parent_dir}/backup1
   if [ -d $dirPath1 ]
   then
      cp -al $dirPath1 $dirPath2
   fi
   # remove old datestamp file from rsync destination
   if test -n "$(find $dirPath1 -maxdepth 1 -name 'MyBackup*' -print -quit)"
   then
      rm $dirPath1/MyBackup*
   fi
   # sync files to backupfolder
   rsync -aq --delete /home $dirPath1
   # create datestamp (empty) file
   touch $dirPath1/"MyBackup from $(date '+%A, %d %B %Y, %T')"
else
   errors=1
fi

# Error handling
if [ $errors != 0 ]
then
   # Select error message based on errors value   
   # errors = 1 => Backup drive not mounted
   fdesc="ERROR with backup"
   case $errors in
      1)
         fbody="Backup location not accessible! Please investigate cause!"
         ;;
      *)
         fbody="Something went wrong. Please investigate!"
         ;;
   esac
   # Error message for screen
   echo $fdesc
   echo $fbody

   ## error email for admin
   receiver="admin@example.com"

   echo $fbody | mail -s "$fdesc" $receiver

   exit
fi

## rsync options
# The option -n can be used to make a dry-run

# The option -P shows the progress

## Description of option switches
# Option -C => CVS exclude
# Option -v => Verbose
# Option -r => Rercursive
# Option -t => Times
# Option -p => Permissions


# An alternative to the above options is option -a
# Option -a => -rlptgoD

# Option -r => Rercursive
# Option -l => links
# Option -p => Permissions
# Option -t => Times
# Option -g => Group
# Option -o => Owner
# Option -D => devices & specials

I have tried to make the comments as explanative as possible.
Now the only thing necessary is to add it to crontab and you’re set to go.

If you have questions or you find an error, please leave a comment.