I’ve a local home server that works as a local RAID storage with some virtual machines that serve different services to me and to some friends. The most known service to most of you is the XMPP service for chat.cat-hackers.net that enables all the H4ck3rZ Foundation members to communicate in an efficient way.

Another thing is that this server hold all of my important data that represents my own work throughout the years, so it’s very important to keep them secure and safe. I’d a bad experience of losing a 2.5GB harddrive that had all of my programming work. That experience taught me how to spend more money to keep your data safe and secure.

So :) I got an external 500GB USB hard drive to have it mainly as a backup drive for my 500GB RAID local home server, and as you can see it’s 500GB too, so I can’t do incremental backups on that disk because it too small for such a plan, so I decided to rsync the data on the storage server to the USB hard drive and I wrote a nice script that does some smart stuff….

Let’s post the script first then I’ll describe more about it..

#AhmedSoliman.com snippets
#let's define some variables
USB_DISK_UUID="c71e0a65-9569-409d-8b7c-5f0c76406217"
USB_DISK_VENDOR="Western"
DEST_BACKUP_DIR="storage_backup"
SNAPSHOT_NAME="storage_snap"
VOLUME_GROUP="storage"
SRC_VOLUME="mystorage"
if (/sbin/lsusb| /bin/grep "$USB_DISK_VENDOR")
then
  #get device name first
  NAME=`/sbin/blkid | grep "$USB_DISK_UUID" |cut -d: -f1`
  if [ -z $NAME ]
  then
    echo "Device was found but UUID doesn't match, we can't detect device node"
    exit 2
  fi

  #check if mounted...

  if /bin/mount | /bin/grep $NAME
  then
    #get the mount point
    MOUNT_POINT=`mount | awk '/'${NAME#/dev/}'/ { print $3}'`
    echo "Usb Disk is already mounted at $MOUNT_POINT"
  else
    #mount manually
    mkdir /tmp/mount.$$
    mount $NAME /tmp/mount.$$
    echo "USB Disk Mounted at /tmp/mount.$$";
    MOUNT_POINT=/tmp/mount.$$
  fi
  #take a snapshot of the source logical volume
  SRC_MOUNT_POINT="/tmp/snapmount.$$"
  mkdir $SRC_MOUNT_POINT
  if /usr/sbin/lvdisplay | grep $SNAPSHOT_NAME
  then
    #snapshot already exists

    mount -o ro /dev/${VOLUME_GROUP}/${SNAPSHOT_NAME} ${SRC_MOUNT_POINT}
    echo "Snapshot of volume $SRC_VOLUME is now mounted at $SRC_MOUNT_POINT";
  else

    if /usr/sbin/lvcreate --size 3gb --snapshot --name $SNAPSHOT_NAME  /dev/${VOLUME_GROUP}/${SRC_VOLUME}
    then
      #created
      mount -o ro /dev/$VOLUME_GROUP/$SNAPSHOT_NAME $SRC_MOUNT_POINT
      echo "Snapshot of volume $SRC_VOLUME is now mounted at $SRC_MOUNT_POINT";
    else
      echo "Couldn't create snapshot for device /dev/$VOLUME_GROUP/$SRC_VOLUME"
      exit 3 ;
    fi

  fi
  rsync -av ${SRC_MOUNT_POINT}/ ${MOUNT_POINT}/${DEST_BACKUP_DIR}/
  sync
  umount $SRC_MOUNT_POINT
  umount $MOUNT_POINT
  echo "Removing snapshot"
  if /usr/sbin/lvremove -f /dev/${VOLUME_GROUP}/${SNAPSHOT_NAME}
  then
    echo "Done"
  else
    echo "Failed!"
    exit 4 ;
  fi
  exit 0
else
  #disk not there...
  echo "USB Storage Couldn't be located...quitting"
  exit 1;
fi 

So, let’s describe the script features.

1- The script uses some variables that define the behaviour, those variables are defined like follows:

USB_DISK_UUID=”c71e0a65-9569-409d-8b7c-5f0c76406217″
“This variable defines the destination USB disk UUID to make sure that we are mounting the correct disk and if you have more than one USB disk attached we want to make sure that we are not destroying the wrong disk. you can know the UUID of the disk using ‘blkid’ command”

USB_DISK_VENDOR=”Western”
“This is the vendor to ensure that we are not wrong detecting the UUID, so we check the output of lspci to make sure that this disk vendor exists in the output”

DEST_BACKUP_DIR=”storage_backup”
“This is the directory that will be created in the destination usb disk that would contain the backup”

SNAPSHOT_NAME=”storage_snap”
“This variables define the snapshot name that would be taken from the storage logical volume, you can set whatever you like here” 

VOLUME_GROUP=”storage”
“This is volume group that contains the storage logical volume”

SRC_VOLUME=”mystorage”
“This is the source logical volume to be backed up”

2- The script makes sure that the usb disk is not already mounted, and if mounted it will detect the current mount point and will work on it.

3- It takes a LVM snapshot of the source storage volume to make sure that the backup is consistent.

4- The script is very efficient in copying changed files (rsync), it takes 2 minutes to make sure that 500GB are in sync (very good timing).

5- There are some other features in the script that you would discover yourself.

I’ll publish a few snippets I wrote gradually… so please don’t hesitate to give me feedback..