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.