Cover V12, i12
dec2003.tar

Listing 2 backup.child script

#!/bin/ksh

filesystem=$1
pathnames=$2
log=$3.$$.log
snapshot=$4
description=$5
retention_period=$6

export PATH=/usr/sbin:${PATH}

# Command variables, used for using "sudo" with the following
# commands: (sudo,) fssnap, mount, umount, su - export them so
# that child processes, will see them properly (su need not)
export sudo="/usr/local/bin/sudo "
if [ ! -x ${sudo} ]; then
    export sudo=""
fi
export fssnap="${sudo}/usr/sbin/fssnap "
export mount="${sudo}/usr/sbin/mount "
export umount="${sudo}/usr/sbin/umount "
su="${sudo}/usr/bin/su"
rm="${sudo}/usr/bin/rm"
mv="${sudo}/usr/bin/mv"
export dsmc="${sudo}/usr/bin/dsmc"

# check for snapshot name of /dev/null - this indicates that 
# there is no actual snapshot to be used as in the case of
# a hot backup's archive logs and control file backup.
if [ "$snapshot" != "/dev/null" ]; then 
    # set the "temporary" mountpoint for the snapshots
    tmpmountpoint="/tmp"
else    tmpmountpoint=""
fi

# we need to mount the backing store file in order to use the snapshot
# of the filesystem for the backup. the snapshots are to be mounted in
# /tmp with the names of the original mount points (ie: the /opt/oracle
# snapshot will be mounted - R/O - as /tmp/opt/oracle which will become
# the target for the "dsmc archive" task. 
#
# in order to mount it we need to create the mount points in the /tmp
# filesystem. to do this we generate a list of pathnames by doing a 
# "dirname" on each parent directory (going backwards up the directory
# tree) and inserting the (parent) directory name in a list (ie: $names)
# previous to the current directory.
#
# ie: using /opt/oracle "$names" starts as: "/tmp/opt/oracle", then 
# becomes "/tmp/opt /tmp/opt/oracle" (should the filesystem name have
# more levels it would have comntinued.) then when names is passed to
# the "mkdir" command the parent directories are created at the same
# time (or "just prior" if you like) preventing errors creating a 
# multi-level mount point name.
 
# this while loop goes on as long as the length of the filesystem name
# (ie: ${#fs}) is greater than one (ie: "/"), each time we go through the
# loop the $fs variable gets "truncated" by making it equal it's parent
# directory name until we get to the root directory.

# Initially set names to blank in case any parent process exported one.
names=""

# check and see if our "temporary" snapshot mountpoint(s) already
# exist, if not make them.
fs=$filesystem
while [ ${#fs} -gt 1 ]
do
    if [ ! -d $tmpmountpoint/$fs ]; then
            names=$tmpmountpoint/$fs" "$names
    fi
        fs=$(dirname $fs)
done
if [ ${#names} -gt 0 ]; then
    mkdir $names
fi

# get the name of the backing store file so we can delete it (later)
# we might want to consider creating the snapshot with the "unlink"
# option, rather than getting the path and deleting it later
# see the fssnap_ufs manpage

# special case exists wth archive logs during HOT backup mode, we do
# not want to the dsmc archives using the snapshot'ed file system,
# as they would get stale copies of the data.

if [ "$snapshot" != "/dev/null" ]; then 
    backing_store=$(${fssnap} -i -o backing-store $filesystem | \
        cut -f2 -d ':')

    logger -ip local1.notice $(basename $0)": Mounting:  " $snapshot \
        "snapshot of:" $filesystem
    # mount the r/o snapshot of our target filesystem
    ${mount} -F ufs -o ro $snapshot ${tmpmountpoint}${filesystem}

fi

# Do the actual dsmc archives... (one command per file, for each one in
# the filesystem.) Here is where we would change the "dsmc" command to
# NetBackup's "bpbackup" or Legato's "save" command(s) should we need
# to use another backup product
all_rc=0
while read pathname
do
    logger -ip local1.notice $(basename $0)": Backing up:" $pathname
    ${dsmc} archive ${tmpmountpoint}${pathname} -filesonly \
	  -archmc=$retention_period -desc=$description >> $log
    rc=$?
    logger -ip local1.notice $(basename $0)": Backup of: " $pathname "rc=" $rc
    echo $pathname "Backup RC=" $rc
    all_rc=$(expr $all_rc + $rc)
done < $pathnames

# umount snapshot mount point, delete the snapshot, remove the
# backing store file, and finally quit.

if [ $all_rc -eq 0 ]; then
if [ "$snapshot" != /dev/null ]; then 
    logger -ip local1.notice $(basename $0)": Unmounting:" $snapshot 
    ${umount} $tmpmountpoint/$filesystem
    # before deleting capture the usage
    ${fssnap} -i -o snapnumber,blockdevname,rawdevname,mountpoint,state,\
backing-store,backing-store-len,maxsize,createtime,chunksize \
$filesystem >> $log
    ${fssnap} -d  $filesystem
    logger -ip local1.notice $(basename $0)": Snapshot:  " $snapshot "deleted"
    ${rm} $backing_store $pathnames
fi
fi

# We are going to leave the temporary mount points in place, they will be 
# deleted by a reboot (if they were created in /tmp)
exit