Team LiB
Previous Section Next Section

Backup Examples

You've got the theory of backups under your belt, and you know some of the tools. Now let's get down to it and start giving some examples of useful methods in which to perform various types of backups.

Using Tar Locally

You may have seen this done, but here is how to tar up all the user's home directories in the /home directory:

   # tar -czvf home-dir-userdirs.tgz /home

The flags (czvf) stand for create, z compress, verbose, and output file. Then the two (or more) options the command takes are the target tgz file (including the file extension) and then the director(ies) to be tar-balled into the target file.

Want something more creative? How about combining the find tool with tar. Use them together to find all new files on the hard drive that belong to the user tweeks and are less than 30 days old, and put them in backup archive:

   # find / -user tweeks -ctime -30 -exec tar Azvf /home/BACKUPS/
   tweeks-new- files.tgz {}\ ;

Or use tar to back up all the standard OS and user files and directories on a system to tape locally:

   # tar czvf /dev/tape /bin /boot /dev /etc /home /lib /lost+found
       /opt /root /sbin /tmp /usr /var

That will back up everything to the tape. One nice command, no unneeded fancy backup software to get in the way.

Caution 

This last tar command is not guaranteed to backup active and changing files. You still must shut off important services and stop writing to key files that you want backed up. The undefined system runlevel of 4 is perfect for shutting down active disk writing services and doing backups. Look back to the Shutting Off Services" section to see how this is accomplished.

Scripting Tar with Runlevel 4

Using the customized runlevel 4 Stop and Back up method (not a Freeze and Copy; that was for the database), we can now apply a simple backup script such as this one to go to runlevel 4, run a set of full tar backups, and e-mail us the results.

#!/bin/bash
## backup-rl -4.sh
## A simple script that switches to runlevel 4, tars up the dirs
## to tape, emails the results, and changes back to the previous runlevel.
## Use the COMPRESS and BACKUPDIRS variables below to change how it runs
## Tape device or symlink expected is /dev/tape.

######## User Variables ###########
RLBAK="4"
##COMPRESS=""                  # compression off=""
COMPRESS="z"                   # compression on="z"
BACKUPDIRS="/bin /boot /dev /etc /home /lib /lost+found /opt /root
  /sbin /tmp /usr /var"
## All dirs "/bin /boot /dev /etc /home /lib /lost+found /opt /root
  /sbin /tmp /usr /var"
MYEMAIL="admin@example.com"
TAPE=/dev/tape

########### Do not change ###########
RL="$(runlevel | cut -f2 -d" ")"
RLORIG="$RL"
CURDIR=$(pwd)

## Do a MySQL-HOT-COPY to /root/mysql-bak
#######################################
echo -Performing a MySQL Hot Copy to /root/mysql-backup
mysqlhotcopy --user=root --allowold --regexp=".*" /root/mysql-backup
echo -MySQL hotcopy complete...

## Change Run Levels and Log Activity
######################################
echo
echo -Current runlevel is $RLORIG
logger -t BACKUP "Runlevel 4 tar backup script was run..."
echo -Changing run levels to $RLBAK for backups
logger -t BACKUP "Changing run levels to $RLBAK for backups"
init "$RLBAK"
sleep 10
echo -Now in runlevel $(runlevel | cut -f2 -d" "), starting backups
logger -t BACKUP "Now in runlel $(runlevel | cut -f2 -d" "), starting backups"
echo " -preparing to backup directories $BACKUPDIRS to tape"
logger it BACKUP " -preparing to backup directories $BACKUPDIRS to tape"

## Do the needful
#######################################
echo "   -rewinding tape"
mt rewind
echo     -tarring content to tape
tar -c$COMPRESS -f $TAPE $BACKUPDIRS > /dev/null 2>&l ERROR=$?
if [ $ERROR -ne 0 ] ; then
  #logger -t BACKUP "Failure in backup script couldn't run tar" $ERROR
  echo "tar errored out this " $ERROR | mail -s "BACKUP FAIL: tar
    could not run" $MYEMAIL
  exit " -FAILURE doing tar" $ERROR
fi
## Cleanup...
###################################
echo -Backups complete...
logger -t BACKUP "Backups complete..."
echo $BACKUPDIRS | mail -s "BACKUP GOOD: directories listed below" $MYEMAIL
echo -Ejecting tape...
mt eject
echo
echo -Returning to runlevel $RLORIG
logger -t BACKUP "Returning to runlevel $RLORIG"
init $RLORIG
echo
sleep 5

echo    Now back in runlevel $Rl
echo -Done

Note 

If you are going to use this type of script, be sure that you are not shutting off syslog if you use the logger logging function to record backup status to the system log.

This is a good example of a backup script that works for performing simple, full system backups. It will get mysql using mysqlhotcopy and everything else (assuming that you have shut such services off in runlevel 4). There are tons of good backup scripts out there for you to choose from-most of them in shell or perl scripts for free. You can find many good backup scripts at http://linux-backup.net.

Tar can handle incremental backups. However, if you want to do level-based incremental/ differential or TOH backups using this script, then you need to do this with dump (see the Using Dump section later in this chapter).

Note 

For more information on tar, see the man tar page, or check out http://linux-backup.net/full_inc.gwif.html.

Using Tar Remotely

A very nice tar trick I like to show is how to use tar (and other such tools) remotely. Most sysadmins are very familiar with ssh (or its older insecure cousin, rsh), but not all have ever used it to transport standard output (or stdout) from a Linux server, over the network to a backup server. This is particularly useful for systems without tape drives.

   # tar cvf - /home /var /etc | ssh root@10.1.1.10 "cat
   >/mnt/backup/remoteserver1_$(date +%Y-%m-%d).tar"

Tip 

Some geek types like to use tar/ssh to go directly to a remote tape device, but I would recommend against using tar/ssh this way. I've seen this cause backup stability problems. I would instead recommend using remote tarring by tarring up your data to what's called a remote holding disk on the remote tape backup machine (as we discussed earlier). After all of your remote servers have pushed their data up to individual holding disk directories on the tape backup server, just have the backup server back up all your remote content from disk to tape. You'll get much better performance and better system predictability.

Using Dump

Dump is probably one of the more fun backup packages. However, you need to be mindful that it is not backing up the file system through the file system as you and other programs see it, but at the block device level. But what makes dump even more sensitive than tar and other such tools to disk content changes is that dump looks at the block device before the backup begins and at all the inodes that it needs to back up. If many of those inodes change before it gets them to tape, these excessive errors can cause dump to abort its backup all together.

This means that before you actually perform a backup, you should definitely use runlevel 4 or a similar method to shut down disk-chatty services, lock and copy your databases (or just shut them off completely), and quiet anything else on the system before using dump to back up to tape. If you do all of this (and are running a supported file system (such as ext2/ext3), then you shouldn't have any problems with dump.

Here's the basic usage for a local dump session doing a level-0 (full) backup to tape by the hard drive device name /dev/hda1:

# dump -Ouf /dev/tape /dev/hda1

This will back up the first file system (/ boot) on the first hard drive to tape (on this particular system). It's fairly fast and will create few (if any) errors if you've sufficiently quieted your system.

Note 

Notice the u option. This is important as it allows you to keep track of the backup dates and levels automatically in the /etc/dumpdates file.

If you have three file systems on your server, /boot, /, and /home (for example), then you do not want to rewind the tape after each backup. This would be bad in that it would only yield the last partition you backed up on the tape. So if you have three partitions on a given disk, you need to use the /dev/nst0 device for at least the first two partitions and then the /dev/st0 or /dev/tape for the last backup on that given tape. These are the three commands that you might want to execute for the first level-0 backup:

dump -Ouf /dev/nst0 /dev/dha1
dump -Ouf /dev/nst0 /dev/dha2
dump -Ouf /dev/st0 /dev/dha3

You might call this your Saturday backup. If you are using the TOH backup plan, what do you think your Monday backup would look like? Probably something like this:

dump -3uf /dev/nst0 /dev/dha1
dump -3uf /dev/nst0 /dev/dha2
dump -3uf /dev/st0 /dev/dha3

If you want to get fancy and also give each day's tape its own dump label, this might help things a bit if tapes get mixed up:

dump -3u -L "L3_2004-03-04_Mon" -f /dev/nst0 /dev/dha1
...

Based on this general usage, we can create a total system backup script. Using some fancy shell script conditionals and the date command, you can autodetect the correct date in our 3-week TOH backup schedule, use the correct related runlevel, and with tools like mysqlhotcopy can build a simple backup script that can pretty much take care of your whole system. Here's a simple example script that employs everything that we've discussed thus far:

#!/bin/bash
# Name:    dump-disks.sh
# Version: v2004-04-26 by tweeks
# Takes:   /dev/dev1 [/dev/dev2] [/dev/dev3]
# Does:    Does modified Tower of Hanoi tape backup on three week rotation
# Details: Looks at day of the week and day of the month and implements a
#          modified TOH dump of /dev/dev1 [/dev/dev2] [/dev/dev3] as per:
#          S S M T W T F
#          0 - 3 2 5 4 7
#          1 - 3 2 5 4 7
#          1 - 3 2 5 4 7
# Output: log to /tmp/backuplog.txt emailed to $MYEMAIL
# Returns: "1" on Sunday error

######## User Variables ############
RLBAK="4"
MYEMAIL="backups@example.com"
TAPEDEV=/dev/nst0       # use the "n" device for no rewind (e.g. /dev/nst0)
MYSQL=/etc/init.d/mysqld
########### Do not change ###########

RL="$(runlevel | cut -f2 -d" ")"
RLORIG="$RL"
CURDIR="$(pwd)"
LEVEL=""
DEV1="$1"
DEV2="$2"
DEV3="$3"

## Detect Day of Week/Month
####################################
# Thanks to Henry Pugsley/Rackspace
dow='date "+%a"' # Day of Week
dom='date "+%d"' # Day of Month
#disks="/dev/hda1 /dev/hda2 /dev/hda3"
if [ $dow == "Sat" ] && [ $dom -lt 7 ] ; then LEVEL=0
elif [ $dow == "Sun" ] ; then echo "Not on Sunday" && exit 1
elif [ $dow == "Sat" ] ; then LEVEL=1
elif [ $dow == "Mon" ] ; then LEVEL=3
elif [ $dow == "Tue" ] ; then LEVEL=2
elif [ $dow == "Wed" ] ; then LEVEL=5
elif [ $dow == "Thu" ] ; then LEVEL=4
elif [ $dow == "Fri" ] ; then LEVEL=7
fl

## Command Line Error Check/Usage
##################################
if [ "$DEV1" = "" ] ; then
  echo
  echo ERROR
  echo "Usage: dump-disks /dev/dev1 [/dev/dev2] [/dev/dev3]"
  echo "Modified TOH backups run Mon-Sat. Will abort on Sundays..."
  exit
fi

#### sanity check ####
echo -----IS THIS RIGHT?------
echo dump-disks.sh about to run like this:
echo    Backup Level=$LEVEL, Backup Devices= $DEV1 , $DEV2 , $DEV3
echo
echo Backup will be:
echo dump -$LEVEL -auL "L$LEVEL_$(date +%Y-%m-%d)" -f $DEV1 $DEV2 $DEV3
echo -----CTRL-C TO STOP------
sleep 10
echo

## Set up logfile: /tmp/backuplog.txt
#######################################
echo dump-disk.sh run on $(date +%Y-%m-%d_%H:%M) by $USERNAME
>/tmp/backuplog.txt
echo"                    o--------------------------------o"
 >>/tmp/backuplog.txt

## Do a MySQL-HOT-COPY to /root/mysql-bak
#######################################
echo -Performing a MySQL Hot Copy to /root/mysql-backup
echo -Performing a MySQL Hot Copy to /root/mysql-backup>>/tmp/backuplog.txt
mkdir -p /root/mysql-backup
# ensure mysql is actually running...
$MYSQL start
mysqlhotcopy --user=root --allowold --regexp=".*" /root/mysql-backup
 >>/tmp/backuplog.txt 2>&1
$MYSQL stop
echo -MySQL hotcopy complete...>>/ tmp/backuplog.txt
echo "                   o-------------------------------o"
 >>/tmp/backuplog.txt

## Change Run Levels and Log Activity
#######################################
echo
echo -Current runlevel is $RLORIG
echo -Changing run levels to $RLBAK for backups init "$RLBAK"
sleep 10
echo -Now in runlel $(runlevel | cut -f2 -d" "), starting backups
echo "-preparing to L-$LEVEL dump Devices=$DEV1, $DEV2, $DEV3 to tape" echo "-preparing to L-$LEVEL dump Devices=$DEV1, $DEV2, $DEV3 to tape"
 >>/tmp/backuplog.txt
## Do the needful
####################################
echo " -rewinding tape"
mt -f $TAPEDEV rewind
# ----------------
if [ "$DEV1" != "" ] ; then
   echo -dump of $DEV1...
   dump -$LEVEL -auL "L$LEVEL_$(date +%Y-%m-%d)" -f $TAPEDEV $DEV1
 >>/tmp/backuplog.txt 2>&1
   echo "                   o--------------------------------o"
 >>/tmp/backuplog.txt
fi
# ----------------
if [ "$DEV?" != ""] ; then
   echo -dump of $DEV2...
   dump -$LEVEL -auL "L$LEVEL_$(date +%Y-%m-%d)" -f $TAPEDEV $DEV2 

 >>/tmp/backuplog.txt 2>&1
   echo "                   o------------------------------o"
 >>/tmp/backuplog.txt
fi
# ----------------
if [ "$DEV3" != ""] ; then
   echo -dump of $DEV3...
   dump -$LEVEL -auL "L$LEVEL_$(date +%Y-%m-%d)" -f $TAPEDEV $DEV3
 >>/tmp/backuplog.txt 2>&1
   echo "                   o--------------------------------o"
 >>/tmp/backuplog.txt
fi

## Cleanup...
###################################
echo -Backups complete...
echo -Ejecting tape...
mt -f $TAPEDEV rewind
echo
echo -Returning to runlevel $RLORIG
init $RLORIG
echo
sleep 5
echo Now back in runlevel $RL
echo -Done >>/tmp/backuplog.txt
echo -Done
if [ "$LEVEL" = "0" ] ; then
   echo | mail -s"Following Backup was Level=0 dump. Make a copy."
 $MYEMAIL
fi
cat /tmp/backuplog.txt | mail -s "$(date +%a) Dump status" $MYEMAIL

The command line usage for backing up to three partitions with this script looks like this:

  # dump-disks.sh /dev/hda1 /dev/hda2 /dev/hda3

And this will give us a modified TOH backup based on the day of the week and the calendar date. Additionally, the first Saturday of the month will always get a level-0 dump and the script will even send us an e-mail reminder to tell us to clone our level-0 tape! This is a configuration that we can fire and forget, and it will be completely automated (except for the insertion of the tapes).

The nice thing about this date smart script configuration is that now we can easily automate this into a daily cronjob and it will know what to do. This is all you need in root's cronjob (by editing with contab -e as root):

########### Smart Three Week TOH Backup Script ############
34 1 * * *      /root/bin/dump-disks.sh /dev/hda1 /dev/hda2 /dev/hda3

And that's it. The smart TOH dump script will now run every morning at 1:34 A.M., and will even autoabort on Sundays (see the script for how this works).

As you can see, with the backup tools provided in most Linux distributions, it doesn't take that much to get an intelligent, hands off, backup configuration set up that makes good use of backup levels, tape usage, and easy recovery strategies. You just need to sit down and plan these things out a bit, and automate things with scripts whenever possible.

If the aforementioned backup script is still a little to "in the rough" for your tastes, you definitely owe it to yourself to check out Amanda at http://backupcentral.com/amanda.html and www.amanda.org. Newer backup suites such as Amanda even go beyond backup levels and the TOH as automate things by simply asking you questions about number of tapes, retention times, and data sets. Very nice indeed!

Using Dump Remotely

Although it is not often done, you can run dump remotely over ssh. You do this with a special usage of dd on the machine with the tape drive on it. The stream is pushed over ssh, into dd on the tape machine, and get put directly to tape. The usage looks like this:

# dump -f - /dev/hda2 | ssh root@backupserver.example.com dd \
 obs=10k of=/dev/st0

Pretty neat! You can also use a pull method from the tape/backup server, like this:

# ssh -n root@desktop.example.com dump f - /dev/hda2 | dd \
 obs=10k of=/dev/nst0

These can be very convenient if you can't be in more than one place at a time.


Team LiB
Previous Section Next Section