Ad-hoc remote backups to tape
I have a nice SCSI tape connected to a single server. This allows for on-demand backups, with the hope (and seldom, with the established knowledge) that I can recover the data I have there.
Old computers, decommissioned computers and systems I wish to erase and reuse are seldom backed-up, just because of the effort in doing it. I will need to manually run something or the other, and who wants this chore?
I know that there are many full-featured backup systems out there, OSS and all, with the capability of doing what I want to do, however, these commonly use backup agents, tape formats and what’s more, just to make a simple one-time backup (which is what I want) – it looked too bloated for my needs.
Again – my needs are: take this machine, run a simple script which can be obtained from an NFS share, wait for X minutes doing something else, and be assured your system is backed up.
I have written the script below to satisfy these requirements. Hope it helps others. Notice the single SSH leading connection and its functionality. It leaves a raw text file on tape with a simple description of the backup process, and the next tracks are the contents of each mount point.
I was a bit spartan with comments, but in general, this script should be quite self-explanatory:
#!/bin/bash # This script will backup local disk to remote tape # Written by Ez-Aton - http://run.tournament.org.il/ SERVER=kruvi # The name of the server with the direct attached tape SRV_USER=root TAPE=/dev/nst0 # Non-rewinding tape. We need to be able to add more tracks and not overwrite our own track SSH="ssh -o StrictHostKeyChecking=no -o ControlMaster=auto -o ControlPath=~/.ssh/socket-%r@%h:%p" WORK_FILE=/tmp/work.$$ TAR_LOG=/tmp/backup.log TAR_ARG="czf - --one-file-system" MOUNTS=`df -TlP | grep -v tmpfs | tail -n +2 | awk '{print $7}'` # Assume nobody is stupid enough to use white spaces in mount paths NUM_MOUNTS=`echo $MOUNTS | wc -w` SUM_FILE=/tmp/summery.txt clean_log () { : > $TAR_LOG } first_disk () { # Assume first disk is the first entry in /proc/partitions DISK="/dev/`cat /proc/partitions | head -n 3 | tail -n 1 | awk '{print $4}'`" } create_sum () { echo "Creating summery" # Collect information and place it in the file. It will be the first track of the tape echo "Hostname: `hostname`" > $SUM_FILE echo >> $SUM_FILE date >> $SUM_FILE echo >> $SUM_FILE for i in $MOUNTS; do df -h $i | tail -n +2 >> $SUM_FILE ; done echo >> $SUM_FILE echo "There will be $(($NUM_MOUNTS + 1)) tracks in addition to the first one" >> $SUM_FILE } create_leading_ssh () { # Use a nice trick for giving password only once: $SSH -f $SRV_USER@$SERVER 'while true; do sleep 100; done' echo "post leading" } monitor_proc () { # Monitor SSH process # Run in the background touch $WORK_FILE PID=`ps aux | grep "$SSH" | grep -v grep | awk '{print $2}'` if [ -z "$PID" ] then echo "Done so soon?" return 1 fi while [ -f $WORK_FILE ] do sleep 10 done kill $PID } test_tape_cmd () { CMD="mt -f $TAPE status" } remote_tape_append () { CMD="cat > $TAPE" } test_tape () { test_tape_cmd if ! $SSH $SRV_USER@$SERVER $CMD then echo "Tape on $SERVER is not ready" exit 1 fi } backup_mount () { # Backup the actual mount # $1 - the path of the mount remote_tape_append if [ -z "$1" ] then echo "Mount path is empty?" exit 1 fi echo "Backing up $1" cd "$1" tar $TAR_ARG . | $SSH $SRV_USER@$SERVER "$CMD" > $TAR_LOG 2>&1 } append_header () { remote_tape_append cat $SUM_FILE | $SSH $SRV_USER@$SERVER "$CMD" } add_mbr () { remote_tape_append first_disk if [ -z "$DISK" ] then echo "Can't decide on the first boot disk. Exiting now" echo "No MBR backup exists" exit 0 fi echo "Backing MBR" dd if=$DISK bs=1M count=1 | $SSH $SRV_USER@$SERVER "$CMD" } create_sum create_leading_ssh monitor_proc & test_tape append_header for i in $MOUNTS do backup_mount $i done add_mbr rm $WORK_FILE