Off Site Backups For Amanda

I use Amanda to back up the computers on my network. I back up to vtapes, or virtual tapes. These are logical tapes stored on an external hard drive. They consist of files, same as any other data on a hard drive. I don't store a lot of data; my backups are in the hundreds of gigabytes range.

The problem comes in when you want to have offsite backups. You need a way to clone the vtapes to multiple external hard drives, so you can rotate them. I have two offsite drives, and I rotate between them weekly. So my offsite backups are at worst a week out of date.

The first script, called back, does the backups. It depends on rsync and assumes that the offsite drive is mounted.

#! /bin/sh

# Time-stamp: <2009-08-12 19:42:57 ccurley back>

# A script to save the backups external drive to an offsite external
# drive.

# Copyright 2006 through the last date of modification, Charles Curley.

offsite=$( mount | grep media/offsite | grep -v myob | cut -d' ' -f3 )

echo $offsite


# options to feed to rsync

opts=" -va --exclude=*~ --delete --delete-excluded"

# path to the external hard drive. No trailing / allowed.

target=${offsite}/myob

echo $target

# The path where the backup directory is located. No trailing /.

source="/media/disk-2"

# Names of the dirs to back up. Use the same name on the external
# drive.


for back in dzur/crc/back amanda ; do

  cmd="rsync $opts ${source}/$back/ ${target}/$back"

  echo $cmd

  $cmd

done

# df -h ${source} ${target}

You'll notice that the target is target=${offsite}/myob. myob is the mount point for mounting the offsite drives encrypted, using ecryptfs. That's why the filter that determines the offsite mount point excludes the word "myob".

I usually call this in a screen session so I can then log out of the machine and let it do its thing.

The next script, offsite.mount, mounts an offsite backup drive. Each such drive has one partition. The key to detecting which drive we have is using the UUID, which we detect with dumpe2fs. It must be run interactively because of the encrypted file system mounting.

#! /bin/sh

# Time-stamp: <2009-07-06 11:58:50 ccurley offsite.mount>

# A script to mount an offsite external drive.

# Copyright 2008 through the last date of modification, Charles Curley.

# Get the UUIDs of the two offsite drives.
uuid1=$(grep '/media/offsite1' /etc/fstab | cut -c6-41)
uuid2=$(grep '/media/offsite2' /etc/fstab | cut -c6-41)

# Now find out which device has one of the two offsite drives.
for dev in $( ls /dev/sd* | grep sd[a-z]$ ) ; do
#   echo $dev

  # It's always the first partition.
  uuid=$( dumpe2fs -h ${dev}1 2>> /dev/null | grep 'Filesystem UUID' | cut -c27-100 )
#   echo $uuid
  if [ $uuid = $uuid1 ] || [ $uuid = $uuid2 ] ; then
    offsite=${dev}1
    echo ${offsite} is the offsite device.
  fi
done

if [ "${offsite}" = '' ] ; then
  echo "Oops! No offsite drive found!"
  return 1
fi

rm /media/offsite

fsck ${offsite}

ret=$?

if [ "$ret" != '0' ] ; then
  echo "fsck error $ret. Stopping."
  return $ret
fi

mount -v ${offsite}

mounted=$(grep ${offsite} /etc/mtab | cut -d ' ' -f 2)

echo Mounting $mounted

mount -t ecryptfs ${mounted}/myob/ ${mounted}/myob/

if [ -e ${mounted}/myob/last.mounted.anc ] ; then
  rm ${mounted}/myob/last.mounted.anc
fi

if [ -e ${mounted}/myob/last.mounted.old ] ; then
  mv ${mounted}/myob/last.mounted.old ${mounted}/myob/last.mounted.anc
fi

if [ -e ${mounted}/myob/last.mounted ] ; then
  mv ${mounted}/myob/last.mounted     ${mounted}/myob/last.mounted.old
fi

date +%F.%T > ${mounted}/myob/last.mounted

ln -s ${mounted} /media/offsite

Notice the two mount points for the offsite drives. You'll have to create those by hand. The last thing is to hide which one is mounted by creating a sym link to the currently mounted drive.

Finally, a script, offsite.umount, to unmount the offsite drive, if any.

#! /bin/sh

# Time-stamp: <2009-07-06 11:50:13 ccurley offsite.umount>

# A script to umount an offsite external drive.

# Copyright 2008 through the last date of modification, Charles Curley.

mounted=$(grep -i offsite /etc/mtab | grep '^/dev/' | cut -d ' ' -f 2)

if [ -e ${mounted}/myob ] ; then
  echo Unmounting $mounted

  umount ${mounted}/myob

  umount ${mounted}

  rm /media/offsite
fi

And that's it! Enjoy.