Management of my shoe-closet computer center requires that I should take some steps to protect the data by taking a backup. In last 10 years, I never took any backup and luckily I was never in the situation to have lost the data. The servers kept on running and runinng without any issue.

The only protection I had was RAID-1 using Linux mdadm commands but even  though disks never failed albeit I changed the disks every 4 years in anticipation that they might fail one day.

As one grows old and develops some silver hair, the attitude towards having life insurance, disk backup, healthy food, less arguments and forgivng people become a priority.

So, I had to struggle one day to make backup of my server in an automated fashion.

I had bought a hard disk enclosure of RAID-1 from ebay in $30 and purchased two 1 TB 5400 rpm disks and put them in the disk enclosure. I also purchased eSata to eSata cable and put this enclosure on the side of the server.

I only thing that I wanted to do was to turn the power switch "on" of the disk enclosure and the backup should be done automatically.

This is what I had to do after lots of googling. I know for sure that I will lose those scripts someday so I have them documented here for my own future references or to help my friends by pointing them to this article.

Step-1: Know disk parameters so that Linux udev can identify it.

# udevadm info -an /dev/sdb
  looking at device '/devices/pci0000:00/0000:00:1f.2/host5/target5:0:0/5:0:0:0/block/sdb':
    KERNEL=="sdb"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{range}=="16"
    ATTR{ext_range}=="256"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="156250000"
    ATTR{alignment_offset}=="0"
    ATTR{discard_alignment}=="0"
    ATTR{capability}=="50"
    ATTR{stat}=="   11896       27    95378     6024      260     2623    23056   180144        0     8204   186164"
    ATTR{inflight}=="       0        0"
    ATTR{events}==""
    ATTR{events_async}==""
    ATTR{events_poll_msecs}=="-1"

  looking at parent device '/devices/pci0000:00/0000:00:1f.2/host5/target5:0:0/5:0:0:0':
    KERNELS=="5:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{device_blocked}=="0"
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="6"
    ATTRS{vendor}=="ATA     "
    ATTRS{model}=="External Disk 0 "
    ATTRS{rev}=="1.15"
    ATTRS{state}=="running"
    ATTRS{timeout}=="30"
    ATTRS{iocounterbits}=="32"
    ATTRS{iorequest_cnt}=="0x2f9f"
    ATTRS{iodone_cnt}=="0x2f9f"
    ATTRS{ioerr_cnt}=="0x1"
    ATTRS{modalias}=="scsi:t-0x00"
    ATTRS{evt_media_change}=="0"
    ATTRS{dh_state}=="detached"
    ATTRS{queue_depth}=="31"
    ATTRS{queue_ramp_up_period}=="120000"
    ATTRS{queue_type}=="simple"

  looking at parent device '/devices/pci0000:00/0000:00:1f.2/host5/target5:0:0':
    KERNELS=="target5:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:1f.2/host5':
    KERNELS=="host5"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/pci0000:00/0000:00:1f.2':
    KERNELS=="0000:00:1f.2"
    SUBSYSTEMS=="pci"
    DRIVERS=="ahci"
    ATTRS{vendor}=="0x8086"
    ATTRS{device}=="0x1c02"
    ATTRS{subsystem_vendor}=="0x1028"
    ATTRS{subsystem_device}=="0x04de"
    ATTRS{class}=="0x010601"
    ATTRS{irq}=="43"
    ATTRS{local_cpus}=="ff"
    ATTRS{local_cpulist}=="0-7"
    ATTRS{modalias}=="pci:v00008086d00001C02sv00001028sd000004DEbc01sc06i01"
    ATTRS{numa_node}=="-1"
    ATTRS{dma_mask_bits}=="64"
    ATTRS{consistent_dma_mask_bits}=="64"
    ATTRS{enable}=="1"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}==""

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

Where /dev/sdb is the name of the disk that was assigned by the udev.

Step-2: Create udev rules. (I call this file 99-backup.rules and copy this in /etc/udev/rules.d directory.)

KERNEL=="sd[b-z]1", SUBSYSTEM=="block", SUBSYSTEMS=="scsi", ATTRS{model}=="External Disk 0", ACTION=="add", SYMLINK+="backup", RUN+="/bin/sh /usr/local/bin/do.backup"

Explanation: I picked, SUBSYSTEM, SUBSYSTEMS, ATTRS{model} parameters from the output of udevadm. The Kernel paramter says that any disk other than sda1 and matching above 3 parameters should be picked up for an Add rule. Symlink says what name to give this disk in /dev and in my case, the disk will be called /dev/backup. You can use /dev/sdb1 but there is no guarantee that udev will assign this name any time you connect the disk so using a symbolic name is always better. We also say that run the script /usr/local/bin/do.backup. This script should finish as soon as possible so we spawn actual backup script from this script. I also used /bin/sh to run this script. I tried putting do.backup in other directory but it seems to work only when I put it in /usr/local/bin. I do not have patience to investigate why it is so.

Step-3: Create backup scripts.

radhey:/usr/local/bin # cat do.backup 
#!/bin/bash
echo "Calling /root/bin/backup now at $(date)" >> /tmp/backup.log
nohup /usr/local/bin/backup &
exit 0

Actual script that does my backup.

radhey:/usr/local/bin # cat backup 
#!/bin/bash

function timer()
{
    if [[ $# -eq 0 ]]; then
        echo $(date '+%s')
    else
        local  stime=$1
        etime=$(date '+%s')

        if [[ -z "$stime" ]]; then stime=$etime; fi

        dt=$((etime - stime))
        ds=$((dt % 60))
        dm=$(((dt / 60) % 60))
        dh=$((dt / 3600))
        printf '%d:%02d:%02d' $dh $dm $ds
    fi
}

tmr=$(timer)
MAILTO=vikram@zinox.com
HOST=`hostname`

echo $(date +"%Y-%m-%d %T") backup started 
sleep 10
mkdir -p /mnt/backup
mount /dev/backup /mnt/backup/
mountpoint /mnt/backup
if [ $? -eq 0 ]
then
  rsync -avz --del root@gopal:/bkp/ /mnt/backup/bkp
  rsync -avz --del root@gopal:/web /mnt/backup/webbackup
  rsync -avz --del root@gopal:/home /mnt/backup/home
  LINE=`printf "Elapsed time: %s\n" $(timer $tmr)`
  if [ $? -eq 0 ]
  then
    umount /mnt/backup
    if [ $? -eq 0 ]
    then
      echo "Backup completed sucessfully. $LINE "| \
           mail -s "$HOST Backup completed" $MAILTO
      exit 0
    else
      echo "Error: Backup completed sucessfully\nBackup \
            Error: Unable to detach device $LINE"| mail -s "$HOST Backup \
            completed with errors" $MAILTO
      exit 2
    fi
    hdparm -Y /dev/backup
  fi
fi

So, I have three directories from other server to backup on this local server. I had to setup password less SSH between two servers. After backup is done, I unmount the disk and use hdparm to spindown the drive so that it does not keep on running. When I remember then I go and powerdown the external drive in my shoe-closet computer center.

The other command that I used to test above was "# udevadm trigger" so that udev can run again and the script is executed instead of going again and again to power down and power up the external disk enclosure.