Better Backups With Tar


Many professional users still lose information due to lack of making good computer file backups, yet Linux provides powerful tools that can help you make backups easily and automatically.

The example script on this page is an improvement of Chapter33.3. Automating backups with tar which shows a basic, yet, effective backup script (Chapter 33 has several other good ideas too).

If you understand how scripts work and are confident with being able to modify one, then you can modify the one shown below to meet your particular circumstances and create an effective, automated backup for yourself and/or custom backups for other users.

The improvements in this script are:

As is mentioned in Chapter33.3. Automating backups with tar, it is also recommended to run this script at the beginning of the month for the first time, then insert the script in the /etc/cron.daily/ directory afterwards and let it run for a month automatically before making any major changes.

STEPS REQUIRED TO SETUP AND AUTOMATE BACKUPS

In the script example shown below, we backup 3 different directories to a backup directory on a local server.

  1. First, create the backup script backup.cron file as shown below so that you can test it out manually. Make sure to use directories 1, 2, 3 according to what you need (this example backs up the directories /home/bird, /home/cat, /home/dog
    #!/bin/sh
    # full and incremental backup script
    # created 07 February 2000
    # Based on a script by Daniel O'Callaghan <danny@freebsd.org>
    # modified by Gerhard Mourani <gmourani@videotron.ca>
    # modified by Jose Da Silva <Digital@JoesCat.com> 08-02-05
    #
    # This script was originally based on above script shown on
    # <http://www.faqs.org/docs/securing/chap29sec306.html> and was
    # modified to backup several directories plus keep a "lastweek"
    # and "prevweek" backups too.
    #
    # If you need to backup directories which contain active files,
    # it is recommended that you do a snapshot of those directories
    # and then do a backup of the snapshot, this way, you have less
    # problems dealing with file-locks and files in transition.
    # If you need to run a snapshot first, just insert a call to the
    # appropriate script at the beginning/end of the main routine below.
    #
    # Change the variables below to fit your computer/backup system
    
    COMPUTER=genesis		# name of this computer
    DIR1="/home/bird"		# directories to backup daily
    DIR2="/home/cat"		# (only 3 examples shown here)
    DIR3="/home/dog"
    BKDIR=/backups			# where to store all the backups
    TIMEDIR=/backups/last-full	# where to store time of full backup
    ERRFILE=/var/log/syslog		# send error messages to this file
    BKOWNER=root.adm		# owner and group for backup files
    
    # Reduce the list of paths to known and trusted directories
    PATH=/usr/local/bin:/usr/bin:/bin
    
    # Name and location of commands so you don't need to search paths
    TAR=/bin/tar			# name and location of commands
    BASENAME=/bin/basename		# (use "which" to find commands)
    CAT=/bin/cat
    DATE=/bin/date
    ECHO=/bin/echo
    CHMOD=/bin/chmod
    CHOWN=/bin/chown
    MKDIR=/bin/mkdir
    MV=/bin/mv
    WHOAMI=/usr/bin/whoami
    
    DOW=`$DATE +%a`			# Day of the week e.g. Mon
    DOM=`$DATE +%d`			# Date of the Month e.g. 27
    MD=`$DATE +%b%d`		# Month and Date e.g. Sep27
    cmd=`$BASENAME "$0"`
    
    # On the 1st of the month, do permanent full backups.
    #
    # Every Sunday, last week's backup is pushed to prevweek's backup
    # and Sunday's backup is pushed to lastweek's backup so that you
    # have 3 weeks worth of a rollover backup.
    #
    # Every Sunday full backups are made - overwriting last Sunday's
    # backups. The rest of the time an incremental backup is made.
    # Each incremental backup overwrites last weeks incremental backup
    # of the same name.
    #
    # if NEWER = "", then tar backs up all files in the directories
    # otherwise it backs up files newer than the NEWER date. NEWER
    # gets its date from the file written every Sunday.
    
    UpdateTheDate() {
      # Update full backup date so increments happen after this
      NOW=`$DATE +"%Y-%m-%d %X"`
      $ECHO "$NOW" > "$TIMEDIR/$COMPUTER-full-date";
      $CHMOD 640 "$TIMEDIR/$COMPUTER-full-date";
      $CHOWN $BKOWNER "$TIMEDIR/$COMPUTER-full-date";
    }
    
    MakeFullMonthlyBackup() {
      # Make a full monthly backup based on given directories
      $TAR -cpzf "$BKDIR/$COMPUTER-$MD-$1.tar.gz" "$2";
      $CHMOD 640 "$BKDIR/$COMPUTER-$MD-$1.tar.gz";
      $CHOWN $BKOWNER "$BKDIR/$COMPUTER-$MD-$1.tar.gz";
    }
    
    MakeFullWeeklyBackup() {
      # Move previous week's backups into prior week's backups
      if [[ -f "$BKDIR/$COMPUTER-$DOW-prevweek-$1.tar.gz" ]]; then
        $MV "$BKDIR/$COMPUTER-$DOW-prevweek-$1.tar.gz" \
            "$BKDIR/$COMPUTER-$DOW-priorweek-$1.tar.gz";
        $CHMOD 640 "$BKDIR/$COMPUTER-$DOW-priorweek-$1.tar.gz";
        $CHOWN $BKOWNER "$BKDIR/$COMPUTER-$DOW-priorweek-$1.tar.gz";
      fi
      # Move last week's backups into previous week's backups
      if [[ -f "$BKDIR/$COMPUTER-$DOW-lastweek-$1.tar.gz" ]]; then
        $MV -f "$BKDIR/$COMPUTER-$DOW-lastweek-$1.tar.gz" \
               "$BKDIR/$COMPUTER-$DOW-prevweek-$1.tar.gz";
        $CHMOD 640 "$BKDIR/$COMPUTER-$DOW-prevweek-$1.tar.gz";
        $CHOWN $BKOWNER "$BKDIR/$COMPUTER-$DOW-prevweek-$1.tar.gz";
      fi
      # Then move this week's full backups into last week's backups
      if [[ -f "$BKDIR/$COMPUTER-$DOW-$1.tar.gz" ]]; then
        $MV "$BKDIR/$COMPUTER-$DOW-$1.tar.gz" \
            "$BKDIR/$COMPUTER-$DOW-lastweek-$1.tar.gz";
        $CHMOD 640 "$BKDIR/$COMPUTER-$DOW-lastweek-$1.tar.gz";
        $CHOWN $BKOWNER "$BKDIR/$COMPUTER-$DOW-lastweek-$1.tar.gz";
      fi
      # Then create a new weekly backup for this day-of-week
      $TAR -cpzf "$BKDIR/$COMPUTER-$DOW-$1.tar.gz" "$2";
      $CHMOD 640 "$BKDIR/$COMPUTER-$DOW-$1.tar.gz";
      $CHOWN $BKOWNER "$BKDIR/$COMPUTER-$DOW-$1.tar.gz";
    }
    
    MakeIncrementalWeeklyBackup() {
      # Make an incremental backup based on date in NEWER file
      $TAR --newer="$1" -cpzf "$BKDIR/$COMPUTER-$DOW-$2.tar.gz" "$3";
      $CHMOD 640 "$BKDIR/$COMPUTER-$DOW-$2.tar.gz";
      $CHOWN $BKOWNER "$BKDIR/$COMPUTER-$DOW-$2.tar.gz";
    }
    
    #----- Main program starts here -----
    if [ "`$WHOAMI`" != "root" ]; then
      $ECHO "$cmd: sorry, you must be root !";
      exit 1
    fi
    
    # Verify backup directory exists, otherwise create it.
    if [[ ! -d "$BKDIR" ]]; then
      $MKDIR "$BKDIR"
      if [[ ! -d "$BKDIR" ]]; then
        $ECHO "$cmd: error, cannot make $BKDIR !" >> $ERRFILE;
        $ECHO "$cmd: error, no backup files made !" >> $ERRFILE;
        exit 2
      else
        $CHMOD 740 "$BKDIR";
        $CHOWN $BKOWNER "$BKDIR";
      fi
    fi
    
    # Verify time directory exists, otherwise create it.
    if [[ ! -d "$TIMEDIR" ]]; then
      $MKDIR "$TIMEDIR"
      if [[ ! -d "$TIMEDIR" ]]; then
        $ECHO "$cmd: error, cannot make $TIMEDIR !" >> $ERRFILE;
        $ECHO "$cmd: error, no backup files made !" >> $ERRFILE;
        exit 3
      else
        $CHMOD 640 "$TIMEDIR"
        $CHOWN $BKOWNER "$TIMEDIR"
      fi
    fi
    
    # Verify time file exists, otherwise create it.
    if [[ ! -f "$TIMEDIR/$COMPUTER-full-date" ]]; then
      UpdateTheDate;
      if [[ ! -f "$TIMEDIR/$COMPUTER-full-date" ]]; then
        $ECHO "$cmd: error, cannot find $TIMEDIR/$COMPUTER-full-date !" \
               >> $ERRFILE;
        $ECHO "$cmd: error, no backup files made !" >> $ERRFILE;
        exit 4
      else
        $CHMOD 640 "$TIMEDIR/$COMPUTER-full-date"
        $CHOWN $BKOWNER "$TIMEDIR/$COMPUTER-full-date"
      fi
    fi
    
    # Create Monthly Backups on 1st day of each month
    if [ $DOM = "01" ]; then
      MakeFullMonthlyBackup "1" "$DIR1" >> $ERRFILE;
      MakeFullMonthlyBackup "2" "$DIR2" >> $ERRFILE;
      MakeFullMonthlyBackup "3" "$DIR3" >> $ERRFILE;
    fi
    
    if [ $DOW = "Sun" ]; then
      # Create Full Weekly Backups on Sundays
      MakeFullWeeklyBackup "1" "$DIR1" >> $ERRFILE;
      MakeFullWeeklyBackup "2" "$DIR2" >> $ERRFILE;
      MakeFullWeeklyBackup "3" "$DIR3" >> $ERRFILE;
    
      UpdateTheDate;
    else
      # Make incremental backups - overwrite last weeks
    
      # Get date of last full backup
      NEWER="`$CAT $TIMEDIR/$COMPUTER-full-date`"
    
      MakeIncrementalWeeklyBackup "$NEWER" "1" "$DIR1" >> $ERRFILE;
      MakeIncrementalWeeklyBackup "$NEWER" "2" "$DIR2" >> $ERRFILE;
      MakeIncrementalWeeklyBackup "$NEWER" "3" "$DIR3" >> $ERRFILE;
    fi

  2. Test your backup.cron file to make sure it runs. You will need to make the backup.cron file executable so that you can test it out manually on the command line.
    [dog@genesis tmp]$ su
    Password: ***
    [root@genesis tmp]# chmod 750 backup.cron
    [root@genesis tmp]# chown root.adm backup.cron
    [root@genesis tmp]# ls -l backup.cron
    -rwxr-x---  1 root adm 6161 Aug  8 21:00 backup.cron*
    [root@genesis tmp]# ./backup.cron

  3. Below is a quick look at the backup directory after a few test runs (the script was modified to use "08" and "Tue" as the first dates so that you can see these results shown here).
    [root@genesis tmp]# ls -l /backups/
    -rw-r-----  1 root adm     2307 Aug  8 21:21 genesis-Aug08-1.tar.gz
    -rw-r-----  1 root adm   367504 Aug  8 21:21 genesis-Aug08-2.tar.gz
    -rw-r-----  1 root adm 32094115 Aug  8 21:22 genesis-Aug08-3.tar.gz
    -rw-r-----  1 root adm      138 Aug  8 21:47 genesis-Tue-1.tar.gz
    -rw-r-----  1 root adm     1289 Aug  8 21:47 genesis-Tue-2.tar.gz
    -rw-r-----  1 root adm     8383 Aug  8 21:47 genesis-Tue-3.tar.gz
    drw-r-----  2 root adm     4096 Aug  8 21:21 last-full/
    
    [root@genesis tmp]# ls -l /backups/last-full/
    -rw-r-----  1 root adm  20 Aug  8 21:21 genesis-full-date

  4. Backups is something you will do often, but you should also verify that your backups are indeed working correctly because restores are something that is seldom done yet very important to do when the time comes to restore a file (or many files). Please check Chapter 33, mentioned above, for steps on how to restore files and directories.

  5. Once you are satisfied that the script appears to run well from the command line, then the next step is to install backup.cron in the cron directory and let your computer run it automatically. You should check the /backups/ directory the next day to verify it holds backups that were made at night.
    [root@genesis tmp]# cp backup.cron /etc/cron.daily/backup.cron
    [root@genesis tmp]# chmod 750 /etc/cron.daily/backup.cron
    [root@genesis tmp]# chown root.adm /etc/cron.daily/backup.cron
    [root@genesis tmp]# ls -l /etc/cron.daily/backup.cron
    -rwxr-x---  1 root adm 6145 Aug  8 23:05 /etc/cron.daily/backup.cron*

NOTES TO THINK ABOUT

Important things to think about when using backup.cron

You may note that doing backups with tar is a disk intensive activity, so if your computer is doing little else at one o'clock in the morning, it's perhaps best to let it finish quickly.

If your computer is a server with additional duties, you may want to add the nice -2 command to make the backup more of a background task to give other processes more priority. This will make backups take longer, but it does allow other processes to run in better priority.

You may note that both this script and the basic script mentioned in Chapter33.3. Automating backups with tar have trouble backing up files that are still in use. If this is the case, you need to add to your backup.cron script a shutdown of the process(es) that cause trouble before you do a backup of that particular directory, then restart the process(es) after tar finishes those directories (for example SQL and other live services). A quicker method to shorten the shutdown time involves taking a snapshot of the troublesome directories, restart the process(es) and making a backup of the snapshot.

Some file systems and some versions of tar are limited to output file sizes of about 2 gigabytes. Make sure you use a recent version of tar and if you find that the output file will be approaching or passing 2 gigabytes, then you should think of using the tar --multi-volume option or you can use split to split the output to multiple files. If you use split then remember to use cat to join the files for restoring.

COMMENTS, ERRORS OR FEEDBACK

It is great if you find this backup.cron script useful, but if you can think of improvements or fixes, please send suggestions using the comment section here so that the script can be improved:

Your Name:
Your Email:
Comments / Suggestions:

Links To Sections Of This How To
Top Of Page Setup Steps Notes Comments

Other Pages On This Web Site
Home Page Disk Image Backup BOINC On Linux Ship Arcade PicDis Disassembler


  
Copyright© 2000..2008 Joe's Cat Website
counter