Tech Corner

Backup script for Linux using tar and find

Every Linux distribution provides a range of utilities that you can use to make backups of your files. It just isn't very straightforward for the average user to setup. Here is how I get the job done with crontab and a shell script using tar and find

Goal

I wanted to backup all the important data on my system on a regular basis. Regular for me implies on an automated nightly basis. I've tried doing a manual backup every week or so but it is a big pain, so effectively I stopped making regular backups....

Additionally, I wanted to have a current backup of the most essential configuration settings on my system, since I tend to have a lot of things customized. This would help me in case of hard drive failure and I had to rebuild from scratch. In case of losing everything I would need to reinstall my Linux distribution anyway (plus the many other software packages) and restore data files and my config settings. I knew that a full backup of the system would be a waste of time and network resources. I only need copies of the important configs and any data that is irreplaceable.

Choice of Hardware

When you talk backups most Unix people think of tapedrives. However, nowadays hard drives are relatively cheap. You can easily add a 2nd or 3rd drive internally to the server and just use it for backups. However, the number one point of failure in a computer is the hardrive with its moving parts. Using a disk array can provide an additional safety net. If you use RAID1 or higher, you can protect yourself by having the data striped across multiple disk spindles which provides fault tolerance if any drive fails. I wanted to have a central device to backup anything attached to my network. So, I chose to add a 1 TeraByte Network Attached Storage appliance running RAID5, called the Buffalo TeraStation. This device has the advantage that the drive can be mounted automatically using SAMBA (Windows File Sharing), no need for manually inserting tapes. A disadvantage is that the backup still resides on hardware that can be prone to failure. The upside is that the TeraStation runs RAID5 with 4 250GB drives. Any one of the disks can fail and I will not lose my data. I can replace the drive and the array will rebuild itself automatically. In addition, since I do have a DVD-burner on my local network, I still have the option to copy a backup to a DVD once in a while.
My main HD is 120GB. The backup NAS device has 1 TeraByte or 1000 MegaBytes of physical storage. By running RAID5 for redundancy, the capacity is actually reduced to 750 GB of storage due to the additional parity data that is written, in order to rebuild the array in the event of failure.

Script

After adding the drive to my machine I wrote a little shell script using bash that basically does the following:

  • Mounts my NAS box using Samba (Windows File Sharing)
  • Checks the date
  • Every Sunday it makes a full backup of most datafiles and configuration settings and older incremental backups are removed. Other days of the week it backs up files that have been accessed within the last day
  • Dumps all the contents of multiple mysql databases to the backup drive and zips the files
  • Retains previous 7 days worth of database backups and removes the remainder
This script stored in /root/scripts is called every night at 3:01 AM by cron. The crontab file looks like:
1 3 * * * /root/scripts/daily_backup

Add this line using crontab -e when root. You will need to know your way around the vi editor to accomplish this. Don't forget you also have to modify the permissions to allow the script to be executable. The script should also be owned by root:root

chown root:root /root/scripts/daily_backup
chmod 750 /root/scripts/daily_backup

Code

Here's the actual code:

#!/bin/bash
#
# creates backups of essential files
#
DATA="/home /root /usr/local"
CONFIG="/etc /var/lib /var/named"
DATABACKUP="/mnt/backup/bofh/data"
CONFIGBACKUP="/mnt/backup/bofh/config"
DATABASEBACKUP="/mnt/backup/bofh/database"
LIST="/tmp/backlist_$$.txt"
#
echo "Starting backup at `date +%Y-%m-%d\ %H:%M:%S`"
echo ""
echo "Mounting Backup Volume..."
mount /mnt/backup
set $(date)
#
if test "$1" = "Sun" ; then
        # weekly a full backup of all data and config. settings:
        #
        echo "Performing Full Data Backup..."
        tar cfz "/mnt/backup/bofh/data/data_full_$6-$2-$3.tgz" $DATA
        echo "Removing incremental data backups..."
        rm -f /mnt/backup/bofh/data/data_diff*
        echo "Removing two week old full backup..."
        find $DATABACKUP -depth -type f \( -ctime +13 -o -mtime +13 \) -print > $LIST
        rm -f `cat $LIST`
        #
        echo ""
        echo "Performing Full Config Backup..."
        tar cfz "/mnt/backup/bofh/config/config_full_$6-$2-$3.tgz" $CONFIG
        echo "Removing incremental config backups..."
        rm -f /mnt/backup/bofh/config/config_diff*
        echo "Removing two week old full config backup..."
        find $CONFIGBACKUP -depth -type f \( -ctime +13 -o -mtime +13 \) -print > $LIST
        rm -f `cat $LIST`
else
        # incremental backup:
        #
        echo "Performing Incremental Data Backup..."
        find $DATA -depth -type f \( -ctime -1 -o -mtime -1 \) -print > $LIST
        tar cfzT "/mnt/backup/bofh/data/data_diff_$6-$2-$3.tgz" "$LIST"
        rm -f "$LIST"
        #
        echo ""
        echo "Performing Incremental config Backup..."
        find $CONFIG -depth -type f  \( -ctime -1 -o -mtime -1 \) -print > $LIST
        tar cfzT "/mnt/backup/bofh/config/config_diff_$6-$2-$3.tgz" "$LIST"
        rm -f "$LIST"
fi
#
# create sql dump of databases:
echo ""
echo "Archiving Database..."
mysqldump -u root --password=mypass --opt mydb > "/mnt/backup/server/database/mydb_$6-$2-$3.sql"
gzip "/mnt/backup/server/database/mydb_$6-$2-$3.sql"
#
echo ""
echo "Removing last week's database backups..."
find $DATABASEBACKUP -depth -type f \( -ctime +6 -o -mtime +6 \) -print > $LIST
rm -f `cat $LIST`
rm -f "$LIST"
#
echo ""
echo "Done!"
echo ""
echo "------------------------------------------------------------------------"
echo "Finished: `date +%Y-%m-%d\ %H:%M:%S`"
echo "------------------------------------------------------------------------"
echo ""
exit 0

Discussion

Data files:
All my data files are in /root, /home or /usr/local.

Settings:
I chose to backup all the config files in /etc (where most essential settings are stored), /var/named (nameserver settings) and /var/lib (not sure about the importance of this one...). I am still far from being a Unix-guru so there may be additional things I need to add. All suggestions are Welcome!


Last Revised: Monday, 09-Apr-2007 21:46:35 EDT


Privacy Statement   SSL Security by 
www.cacert.org