From: wirzeniu@klaava.Helsinki.FI (Lars Wirzenius)
Newsgroups: comp.os.linux
Subject: Re: Backups
Date: 11 Sep 92 21:01:07 GMT
Organization: University of Helsinki

butler@cs.tulane.edu (Larry Butler) writes:
>How do I make a backup of a file system on to floppies?

I use GNU tar myself.  The sources from GNU come with two shell scripts
that can be used to make backups, level-0 for a full dump, and level-1
for files changed since the last full dump.

Unfortunately, these scripts don't works right out of the box, since
they use commands not commonly available on Linux (mt, mail, perhaps
others).  I had to hack at them for a while until they worked.  I
recently offered to mail them to interested parties, and did to all two
of them, but I guess I'll post too, since there may be more people who
might use them.

However, please be warned that these scripts have been hacked and that
they are _ugly_.  There is no need to tell it to me.  Of course, if you
happen to find a bug, I'd be glad to hear about it (I have about 18
months' work depending on this backup strategy, but do _not_ take this
as a statement of quality: I gamble almost without provocation).

To use them, you need to customize backup-specs, which defines the
filesystems or directories that will be backed up.

--
Lars.Wirzenius@helsinki.fi


---8<---cut here for level-0 ---8<---
#!/bin/sh
#
# Run this script as root on the machine that has the tape drive, to make a
# full dump.
#
# If you give `now' as an argument, the dump is done immediately.
# Otherwise, it waits until 1am, or until the hour given as argument.
# Specify the hour as a number from 0 to 23.
#
# You must edit the file `backup-specs' to set the parameters for your site.

if [ ! -w / ]; then
   echo The backup must be run as root,
   echo or else some files will fail to be dumped.
   exit 1
else
   false
fi

# This is undesirable -- rms.
# rsh albert /usr/local/adm/motd-backup-start

# Get the values of BACKUP_DIRS and BACKUP_FILES, and other variables.
. ./backup-specs

# Maybe sleep until around specified or default hour.
#
if [ "$1" != "now" ]; then
   if [ "$1"x != x ]; then
      spec=$1
   else
      spec=$BACKUP_HOUR
   fi
   pausetime=`date | awk '{hr=substr($4,1,2);\\
      mn=substr($4,4,2);\\
      if((hr+0)<spec)\\
         print 3600*(spec-hr)-60*mn;\\
      else\\
         print 3600*(spec+(24-hr))-60*mn; }' spec=$spec`
   clear
   cat ./dont_touch
   sleep $pausetime
fi

# start doing things

here=`pwd`
LOGFILE=log`date '+%m%d'`full
HOST=`hostname | sed 's/\..*//'`
TAR_PART1="/bin/tar -c +multi-volume +block=$BLOCKING +sparse +exclude-from -"
#TAR_PART1="/usr/local/bin/tar -c +multi-volume +one-file-system +block=$BLOCKING "

# Make sure the log file did not already exist.  Create it.

if [ -f $LOGFILE ] ; then
   echo Log file $LOGFILE already exists.
   exit 1
else
   touch $LOGFILE
fi

#mt -f $TAPE_FILE rewind

set $BACKUP_DIRS
while [ $# -ne 0 ] ; do
   host=`echo $1 | sed 's/:.*$//'`
   fs=`echo $1 | sed 's/^.*://'`
   date=`date`
   fsname=`echo $1 | sed 's/\//:/g'`

   TAR_PART2="+listed=/etc/tar-backup/temp.lev0 "
   TAR_PART3="+label='Full backup of $fs on $host at $date' -C $fs ."

   echo Backing up $1 at $date | tee -a $LOGFILE

   # Actually back things up.

   if [ $HOST != $host ] ; then
      rsh $host "mkdir /etc/tar-backup 2>/dev/null; \
	rm -f /etc/tar-backup/temp.lev0; \
      	$TAR_PART1 -f $HOST:$TAPE_FILE $TAR_PART2 $TAR_PART3" \
	 2>&1 | tee -a $LOGFILE
   else
      mkdir /etc/tar-backup 2>/dev/null
      rm -f /etc/tar-backup/temp.lev0
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
      echo -n "Insert first volume for $1 and press Enter"; read dummy
      echo "$EXCLUDE_FILES" | tr ' ' '\12' | \
        sh -c "exec $TAR_PART1 -f $TAPE_FILE $TAR_PART2 $TAR_PART3" 2>&1 | \
        tee -a $LOGFILE
   fi
   if [ $? -ne 0 ] ; then
      echo Backup of $1 failed. | tee -a $LOGFILE
      # I'm assuming that the tar will have written an empty
      # file to the tape, otherwise I should do a cat here.
   else
      if [ $HOST != $host ] ; then
	rsh $host mv -f /etc/tar-backup/temp.lev0 /etc/tar-backup/$fsname.lev0 2>&1 | tee -a $LOGFILE
      else
        mv -f /etc/tar-backup/temp.lev0 /etc/tar-backup/$fsname.lev0 2>&1 | tee -a $LOGFILE
      fi
   fi
   $TAPE_STATUS | tee -a $LOGFILE
#   sleep 60
   shift
done

# Dump any individual files requested.

if [ x != "x$BACKUP_FILES" ] ; then
   date=`date`

   TAR_PART2="+listed=/etc/tar-backup/temp.lev0"
   TAR_PART3="+label='Full backup of miscellaneous files at $date'"

   mkdir /etc/tar-backup 2>/dev/null
   rm -f /etc/tar-backup/temp.lev0

   echo Backing up miscellaneous files at $date | tee -a $LOGFILE
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
   echo -n "Insert first volume for $1 and press Enter"; read dummy
   echo "$EXCLUDE_FILES" | tr ' ' '\12' | \
     sh -c "exec $TAR_PART1 -f $TAPE_FILE $TAR_PART2 $TAR_PART3 \
     $BACKUP_FILES" 2>&1 | tee -a $LOGFILE
   if [ $? -ne 0 ] ; then
     echo Backup of miscellaneous files failed. | tee -a $LOGFILE
     # I'm assuming that the tar will have written an empty
     # file to the tape, otherwise I should do a cat here.
   else
     mv -f /etc/tar-backup/temp.lev0 /etc/tar-backup/misc.lev0 2>&1 | tee -a $LOGFILE
   fi
   $TAPE_STATUS | tee -a $LOGFILE
else
   echo No miscellaneous files specified | tee -a $LOGFILE
   false
fi

#mt -f $TAPE_FILE rewind
#mt -f $TAPE_FILE offl

echo Sending the dump log to $ADMINISTRATOR
#cat $LOGFILE | sed -f logfile.sed > $LOGFILE.tmp
#mail -s "Results of backup on `date`" $ADMINISTRATOR < $LOGFILE.tmp
(echo ''; echo "Subject: Results of backup on `date`"; echo '';
cat $LOGFILE) >> /usr/spool/mail/root

# This is undesirable -- rms.
#rsh albert /usr/local/adm/motd-backup-done &

---8<---cut here for level-1 ---8<---
#!/bin/sh
#
# Run this script as root on the machine that has the tape drive, to make a
# level-1 dump containing all files changed since the last full dump.
#
# If you give `now' as an argument, the dump is done immediately.
# Otherwise, it waits until 1am.
#
# You must edit the file `backup-specs' to set the parameters for your site.

if [ ! -w / ]; then
   echo The backup must be run as root,
   echo or else some files will fail to be dumped.
   exit 1
else
   false
fi

# Get the values of BACKUP_DIRS and BACKUP_FILES, and other variables.
. ./backup-specs

# Maybe sleep until around specified or default hour.
#
if [ "$1" != "now" ]; then
   if [ "$1"x != x ]; then
      spec=$1
   else
      spec=$BACKUP_HOUR
   fi
   pausetime=`date | awk '{hr=substr($4,1,2);\\
      mn=substr($4,4,2);\\
      if((hr+0)<spec)\\
         print 3600*(spec-hr)-60*mn;\\
      else\\
         print 3600*(spec+(24-hr))-60*mn; }' spec=$spec`
   clear
   cat ./dont_touch
   sleep $pausetime
fi

# start doing things

here=`pwd`
LOGFILE=log`date '+%m%d'`lev1
HOST=`hostname | sed 's/\..*//'`
TAR_PART1="/bin/tar -c +multi-volume +block=$BLOCKING +sparse +exclude-from -"
#TAR_PART1="/usr/local/bin/tar -c +multi-volume +one-file-system +block=$BLOCKING "

# Make sure the log file did not already exist.  Create it.

if [ -f $LOGFILE ] ; then
   echo Log file $LOGFILE already exists.
   exit 1
else
   touch $LOGFILE
fi

#mt -f $TAPE_FILE rewind

set $BACKUP_DIRS
while [ $# -ne 0 ] ; do
   host=`echo $1 | sed 's/:.*$//'`
   fs=`echo $1 | sed 's/^.*://'`
   date=`date`
   fsname=`echo $1 | sed 's/\//:/g'`

# This filename must be absolute; it is opened on the machine that runs tar.
   TAR_PART2="+listed=/etc/tar-backup/temp.lev1"
   TAR_PART3="+label='level 1 backup of $fs on $host at $date' -C $fs ."

   echo Backing up $1 at $date | tee -a $LOGFILE
   echo Last full dump on this filesystem: | tee -a $LOGFILE

   if [ $HOST != $host ] ; then
     rsh $host "ls -l /etc/tar-backup/$fsname.lev0; \
	cp /etc/tar-backup/$fsname.lev0 /etc/tar-backup/temp.lev1" \
	2>&1 | tee -a $LOGFILE
   else
     ls -l /etc/tar-backup/$fsname.lev0 2>&1 | tee -a $LOGFILE
     cp /etc/tar-backup/$fsname.lev0 /etc/tar-backup/temp.lev1 2>&1 | tee -a $LOGFILE
   fi

   # Actually back things up.

   if [ $HOST != $host ] ; then
      rsh $host $TAR_PART1 -f $HOST:$TAPE_FILE $TAR_PART2 $TAR_PART3 2>&1 | tee -a $LOGFILE
   else
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
      echo -n "Insert first volume for $1 and press Enter"; read dummy
      echo "$EXCLUDE_FILES" | tr ' ' '\12' | \
        sh -c "exec $TAR_PART1 -f $TAPE_FILE $TAR_PART2 $TAR_PART3" 2>&1 | \
        tee -a $LOGFILE
   fi
   if [ $? -ne 0 ] ; then
      echo Backup of $1 failed. | tee -a $LOGFILE
      # I'm assuming that the tar will have written an empty
      # file to the tape, otherwise I should do a cat here.
   else
      if [ $HOST != $host ] ; then
	rsh $host mv -f /etc/tar-backup/temp.lev1 /etc/tar-backup/$fsname.lev1 2>&1 | tee -a $LOGFILE
      else
        mv -f /etc/tar-backup/temp.lev1 /etc/tar-backup/$fsname.lev1 2>&1 | tee -a $LOGFILE
      fi
   fi
   $TAPE_STATUS  | tee -a $LOGFILE
#   sleep 60
   shift
done

# Dump any individual files requested.

if [ x != "x$BACKUP_FILES" ] ; then
   date=`date`
   TAR_PART2="+listed=/etc/tar-backup/temp.lev1"
   TAR_PART3="+label='Incremental backup of miscellaneous files at $date'"

   echo Backing up miscellaneous files at $date | tee -a $LOGFILE
   echo Last full dump of these files: | tee -a $LOGFILE  
   ls -l /etc/tar-backup/misc.lev0 2>&1 | tee -a $LOGFILE

   rm -f /etc/tar-backup/temp.lev1 2>&1 | tee -a $LOGFILE
   cp /etc/tar-backup/misc.lev0 /etc/tar-backup/temp.lev1 2>&1 | tee -a $LOGFILE

   echo Backing up miscellaneous files at $date | tee -a $LOGFILE
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
   echo -n "Insert first volume for $1 and press Enter"; read dummy
   echo "$EXCLUDE_FILES" | tr ' ' '\12' | \
     sh -c "exec $TAR_PART1 -f $TAPE_FILE $TAR_PART2 $TAR_PART3 \
      $BACKUP_FILES" 2>&1 | tee -a $LOGFILE
   if [ $? -ne 0 ] ; then
     echo Backup of miscellaneous files failed. | tee -a $LOGFILE
     # I'm assuming that the tar will have written an empty
     # file to the tape, otherwise I should do a cat here.
   else
     mv -f /etc/tar-backup/temp.lev1 /etc/tar-backup/misc.lev1 2>&1 | tee -a $LOGFILE
   fi
   $TAPE_STATUS | tee -a $LOGFILE
else
   echo No miscellaneous files specified | tee -a $LOGFILE
   false
fi

#mt -f $TAPE_FILE rewind
#mt -f $TAPE_FILE offl

echo Sending the dump log to $ADMINISTRATOR
#cat $LOGFILE | sed -f logfile.sed > $LOGFILE.tmp
#/usr/ucb/mail -s "Results of backup on `date`" $ADMINISTRATOR < $LOGFILE.tmp
(echo ''; echo "Subject: Results of backup on `date`"; echo '';
cat $LOGFILE) >> /usr/spool/mail/root

---8<--- cut here for backup-specs
# site-specific parameters for file system backup.

# User name of administrator of backups.
ADMINISTRATOR=root

# Hour at which backups are normally done.
# This should be a number from 0 to 23.
BACKUP_HOUR=1

# Device to use for dumping.  It should be on the host
# on which the dump scripts are run.
TAPE_FILE=/dev/fd0

# Command to obtain status of tape drive, including error count.
# On some tape drives there may not be such a command;
# then simply use `TAPE_STATUS=false'.
TAPE_STATUS=false

# Blocking factor to use for writing the dump.
BLOCKING=20

# List of file systems to be dumped.
# Actually, any directory may be used,
# but if it has subdirectories on other file systems,
# they are not included.

# The host name specifies which host to run tar on.
# It should normally be the host that actually has the file system.
# If GNU tar is not installed on that machine,
# then you can specify some other host which can access
# the file system through NFS.
# Although these are arranged one per line, that is not mandatory.
# It does not work to use # for comments within the string.
BACKUP_DIRS="haven:/"

# List of individual files to be dumped.
# These should be accesible from the machine on which the dump is run.
BACKUP_FILES=""

# List of files to be excluded from backups
EXCLUDE_FILES="swapfile tmp bin lib usr/bin usr/lib usr/tmp msdos/bin mnt"
Newsgroups: comp.os.linux