From: hlu@eecs.wsu.edu (H.J. Lu)
Newsgroups: comp.os.linux
Subject: Re: Backing Up Linux
Keywords: backups, disk, multi-volume, tar
Date: 7 Oct 92 17:14:24 GMT
Article-I.D.: serval.1992Oct7.171424.12072
Organization: School of EECS, Washington State University

In article <1aulspINNe7u@uwm.edu>, rick@ee.uwm.edu (Rick Miller) writes:
|> Doing a `tar -h` shows me that there's much more to the GNU tar than I
|> understand...  It appears that GNU tar knows how to make multi-volume
|> '.tar' files and how to archive directly to disk, but *I* don't know how.
|> 
|> Where could I get some good documentation on GNU tar?

No such a thing, except for source code. A doc was said to be out with
tar 1.12.

|> Do all these features work under Linux?

I never tried all of them.

|> 
|> I'm thinking that with my meager 27 Megabyte Linux partition, and that only
|> fractionally filled at the moment, I might do an easy backup by doing:
|> 
|> 	tar -cvf - / | compress | tar -c[multi-disk options]
|> 
|> 		the first 'tar' being used to *collect* all the files,
|> 		and the second 'tar' being used to save the archive to
|> 		multiple floppies in a multi-volume sort of way. (?)
|> 
|> Will this work?  Is there a better way?  What about:
|> 
|> 	tar -cvz[multi-disk options] /
|> 	       ^ Does the "z" option work when *creating* such an archive?
|> 
|> Rick Miller   <rick@ee.uwm.edu> | <rick@discus.mil.wi.us>   Ricxjo Muelisto
|> Occupation:  Husband, Father, WEPCo. WAN Mgr., Discus Sys0p, and  Linux fan

This is what I use for backing up the hd in school. Hope it helps.

H.J.
-----

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by H.J. Lu <hlu@irl> on Wed Oct  7 10:09:35 1992
#
# This archive contains:
#	level-0		level-1		backup-specs	
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo x - level-0
sed 's/^@//' >level-0 <<'@EOF'
#!/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+0))\\
         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 | awk '{print $2 "-" $3 "-" $6}'`-full
HOST=`hostname | sed 's/\..*//'`
TAR_PART1="/usr/local/bin/gnutar -c --multi-volume --one-file-system --block=$BLOCKING --sparse --volno-file=$VOLNO_FILE --atime-preserve"

# 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
mt -t $TAPE_FILE rew
rm $VOLNO_FILE

if [ "x${BACKUP_DIRS}x" != xx ]; then
  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.level-0"
     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
        # Removed 2>&1/dev/null cruft since that's incorrect sh syntax.
        rsh $host mkdir /etc/tar-backup > /dev/null 2>&1
        rsh $host rm -f /etc/tar-backup/temp.level-0
        rsh $host $TAR_PART1 -f $HOST:$TAPE_FILE $TAR_PART2 $TAR_PART3 2>&1 | tee -a $LOGFILE
     else
        mkdir /etc/tar-backup > /dev/null 2>&1
        rm -f /etc/tar-backup/temp.level-0
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
        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.level-0 /etc/tar-backup/$fsname.level-0" 2>&1 | tee -a $LOGFILE
        else
          mv -f /etc/tar-backup/temp.level-0 /etc/tar-backup/$fsname.level-0 2>&1 | tee -a $LOGFILE
        fi
     fi
     $TAPE_STATUS | tee -a $LOGFILE
     sleep 60
     shift
  done
fi

# Dump any individual files requested.

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

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

   mkdir /etc/tar-backup > /dev/null 2>&1
   rm -f /etc/tar-backup/temp.level-0

   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.
   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.level-0 /etc/tar-backup/misc.level-0 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
sleep 5
mt -t $TAPE_FILE rew
#mt -t $TAPE_FILE offl

echo Sending the dump log to $ADMINISTRATOR
#cat $LOGFILE | sed -f logfile.sed > $LOGFILE.tmp
cp $LOGFILE $LOGFILE.tmp
if [ -f /net/local/bin/elm ]
then
  MAILER=/net/local/bin/elm
else
  MAILER=/usr/bin/mailx
fi
$MAILER -s "Results of backup on `date`" $ADMINISTRATOR < $LOGFILE.tmp

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

chmod 777 level-0

echo x - level-1
sed 's/^@//' >level-1 <<'@EOF'
#!/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+0)\\
         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 | awk '{print $2 "-" $3 "-" $6}'`-level-1
HOST=`hostname | sed 's/\..*//'`
TAR_PART1="/usr/local/bin/gnutar -c --multi-volume --one-file-system --block=$BLOCKING --sparse --volno-file=$VOLNO_FILE --atime-preserve"

# 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
mt -t $TAPE_FILE rew
rm $VOLNO_FILE

if [ "x${BACKUP_DIRS}x" != xx ]; then
  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.level-1"
     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.level-0; \
  	cp /etc/tar-backup/$fsname.level-0 /etc/tar-backup/temp.level-1" \
  	2>&1 | tee -a $LOGFILE
     else
       ls -l /etc/tar-backup/$fsname.level-0 2>&1 | tee -a $LOGFILE
       cp /etc/tar-backup/$fsname.level-0 /etc/tar-backup/temp.level-1 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.
        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.level-1 /etc/tar-backup/$fsname.level-1 2>&1 | tee -a $LOGFILE
        else
          mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/$fsname.level-1 2>&1 | tee -a $LOGFILE
        fi
     fi
     $TAPE_STATUS  | tee -a $LOGFILE
     sleep 60
     shift
  done
fi

# Dump any individual files requested.

if [ x != "x$BACKUP_FILES" ] ; then
   date=`date`
   TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
   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.level-0 2>&1 | tee -a $LOGFILE

   rm -f /etc/tar-backup/temp.level-1 2>&1 | tee -a $LOGFILE
   cp /etc/tar-backup/misc.level-0 /etc/tar-backup/temp.level-1 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.
   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.level-1 /etc/tar-backup/misc.level-1 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 -t $TAPE_FILE rew
#mt -f $TAPE_FILE offl

echo Sending the dump log to $ADMINISTRATOR
cat $LOGFILE | sed -f logfile.sed > $LOGFILE.tmp
if [ -f /net/local/bin/elm ]
then
  MAILER=/net/local/bin/elm
else
  MAILER=/usr/bin/mailx
fi
$MAILER -s "Results of backup on `date`" $ADMINISTRATOR < $LOGFILE.tmp
@EOF

chmod 777 level-1

echo x - backup-specs
cat >backup-specs <<'@EOF'
# site-specific parameters for file system backup.

# User name of administrator of backups.
ADMINISTRATOR=hlu

# 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/rmt/0mn

# 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="mt -t $TAPE_FILE"
TAPE_STATUS=false

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

# Name of temporary file to hold volume numbers.  This needs to be accessible
# by all the machines which have filesystems to be dumped.
VOLNO_FILE=/usr/tmp/dump/volnofile

# 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="
	irl:/users"

#	albert:/fs/fsf
#	apple-gunkies:/gd
#	albert:/fs/gd2
#	nutrimat:/fs/gp
#	nutrimat:/fs/gp2
#	albert:/fs/mailer
#	albert:/
#	albert:/usr
#	apple-gunkies:/
#	apple-gunkies:/usr
#	nutrimat:/
#	placebo:/archive
#	placebo:/
#	wombat:/
#	wombat:/usr
#	wombat:/usr1
#	gnu:/
#	gnu:/usr
#	ernst:/usr1
#	nutrimat:/fs/dist"

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

chmod 666 backup-specs

exit 0