[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Need help/feedback on backup script



FWIW, here's mine. -chris

#!/bin/sh

VOLUME=/zip
DISK=1

_pre()
{
    printf "Make sure your ZIP drive is plugged in.\n"
    printf "Press <Enter> when ready, or 'quit' to quit "
    read ANSWER
    if [ "${ANSWER}" = "quit" ]; then
	exit 0
    fi
    sudo modprobe imm
    cd /
}

_post()
{
    sudo rmmod imm
}

_backup()
{
    false
    while [ $? -ne 0 ]; 
    do
	printf "Insert ZIP disk ${DISK} and press <Enter> when ready "
	printf "to continue.\n(Type 'skip' if you want to skip this disk)\n"
	read ANSWER
	if [ "${ANSWER}" = "skip" ]; then
	    DISK=`expr ${DISK} + 1`
	    return
	fi
	umount ${VOLUME} >> /dev/null 2>&1
	mount ${VOLUME}
    done
    while true;
    do
	sudo kbackup $*
	if [ $? -ne 0 ]; then
	    printf "Backup failed for disk ${DISK}. Try again or type 'skip' to \n"
	    printf "skip to the next disk.\n"
	    read ANSWER
	    if [ "${ANSWER}" = "skip" ]; then
		break
	    fi
	else
	    break
	fi
    done
    DISK=`expr ${DISK} + 1`
}

printf "Hello, this is your friendly system backup script.\n"
printf "Preparing to back up everything...\n"

_pre

_backup -v /

_backup -vz /home/krzys 

_backup -vz /usr/local 

_backup -v /var

_post

printf "Done backing up everything.\n"
printf "Press <Enter> to finish.\n"
read


# and here's kbackup:

#!/bin/sh

#
# Run this as "backup" or "verify" or "restore".
# Verify is only really useful in compressed mode (-z).
# When run as "new-volume-script", unmounts and ejects the disk,
# then prompts to continue.
#

# These variables are global, you can change their value but don't remove them
PRGNAME=`basename $0`
OPTSTRING=tfzvnmx:
EJECT=/usr/local/sbin/eject # an incantation for ejecting the ZIP disk
TAPELENGTH=98078 #kB
TAR=tar
MOUNT=mount
UNMOUNT=umount
VOLUME=/zip
COMPRESS=false
VERBOSE=false
EJECT_WHEN_DONE=true
MULTIVOLUME=false
TEST=false
OVERWRITE=false
MOUNTED=false
NEWVOLUMESCRIPT=`dirname $0`/new-volume-script # should be a symlink to us
# list of files to exclude, read the tar documentation very carefully
EXCLUDE_FILE=/var/local/kbackup/exclude  
EXCLUDE=`cat ${EXCLUDE_FILE}`
BACKUPROOT=
ARGS=
FILES=
FILENAME=
LABELNAME=
TARGET=
TARLONGFLAGS=
ZIPCOMMAND= # hacky! should be used only in _verify()
TARCOMMAND=

_usage()
{
    printf "Usage: $0 [-${OPTSTRING}] " 1>&2
    if [ "${PRGNAME}" = "restore" ]; then
	printf "archive [files]\n" 1>&2
    else
	printf "directory(or file)-list\n" 1>&2
    fi
    printf "  -z\t\tcompressed archive\n" 1>&2
    printf "  -v\t\tverbose\n" 1>&2
    printf "  -n\t\tdon't eject disk when finished\n" 1>&2
    printf "  -m\t\tmulti-volume archive\n" 1>&2
    printf "  -x file\texclude this file\n" 1>&2
    printf "  -f\t\toverwrite existing files\n" 1>&2
    printf "  -t\t\tprint the command but don't actually do the job\n" 1>&2
    exit 1
}

_mount()
{
    ${UNMOUNT} ${VOLUME} 2>> /dev/null
    if [ $? -eq 0 ]; then
	MOUNTED=true
    fi
    if ! ${MOUNT} ${VOLUME}; then
	printf "Failed to mount ${VOLUME}, exiting\n"
	exit 1
    fi
}

_args()
{
    # need to call getopt twice because 'set' seems to always return zero
    getopt ${OPTSTRING} $* >> /dev/null
    if [ $? != 0 ]; then
	_usage
    fi
    set -- `getopt ${OPTSTRING} $*`
    for i
	do
	case "$i" in
	    -t)
		TEST=true
		shift
		;;
	    -x)
		EXCLUDE="${EXCLUDE} $2"
		shift
		shift
		;;
	    -n)
		EJECT_WHEN_DONE=false
		shift
		;;
	    -m)
		MULTIVOLUME=true
		shift
		;;
	    -z)
		COMPRESS=true
		shift
		;;
	    -v)
		VERBOSE=true
		shift
		;;
	    --)
		shift
		break
		;;
# this breaks option arguments
#  		    *)		    
#  		    printf "Invalid option '%s', exiting\n" $i
#  		    exit 1
#  		    ;;
	esac
    done
    if [ "${COMPRESS}" = true -a "${MULTIVOLUME}" = true ]; then
	printf "Multi-volume archives can't be compressed, exiting\n"
	exit 1
    fi
    ARGS=$*
}
    
_backup()
{
    TARFLAGS="vcSlpf"
    TARLONGFLAGS="--absolute-names --one-file-system --totals --label=${LABELNAME} --atime-preserve " # --exclude-from=${EXCLUDE_FILE} "
    if [ "${COMPRESS}" = true ]; then
	TARFLAGS="z""${TARFLAGS}"
	TARGET=${BACKUPROOT}/${FILENAME}.tar.gz
    else
	TARGET=${BACKUPROOT}/${FILENAME}.tar
#	TARFLAGS="W""${TARFLAGS}"
	if [ "${MULTIVOLUME}" = true ]; then
	    TARLONGFLAGS="${TARLONGFLAGS}"" --multi-volume --tape-length=${TAPELENGTH} --new-volume-script=${NEWVOLUMESCRIPT}"
#  	else
#  	    TARFLAGS="W""${TARFLAGS}"
	fi
    fi
    EXCLUDE="${TARGET} ${EXCLUDE}"
    for i in ${EXCLUDE}
    do
	# remove leading and trailing slash
	# i=`echo ${i} | sed -e 's/^\///' | sed -e 's/\/$//'`
	# remove leading and trailing "*" if any
	# i=`echo ${i} | sed -e 's/^\*//' | sed -e 's/\*$//'`
	# put them back in (pre-1.13.17 versions of tar may have this bug)
	# i="*"${i}"*"
	TARLONGFLAGS="--exclude=$i ${TARLONGFLAGS}"
    done
    printf "Backing up %s to %s...\n" "${FILES}" ${TARGET}
    TARCOMMAND="${TAR} ${TARFLAGS} ${TARGET} ${TARLONGFLAGS} ${FILES}"
    _run
}

_verify()
{
    TARLONGFLAGS="--compare --one-file-system" #--exclude-from=${EXCLUDE_FILE}"
    if [ "${COMPRESS}" = true ]; then
	TARLONGFLAGS="--gunzip ${TARLONGFLAGS}"
	TARGET=${BACKUPROOT}/${FILENAME}.tar.gz
    else	
	TARGET=${BACKUPROOT}/${FILENAME}.tar
	if [ "${MULTIVOLUME}" = true ]; then
	    TARLONGFLAGS="${TARLONGFLAGS} --multi-volume --tape-length=${TAPELENGTH} --new-volume-script=${NEWVOLUMESCRIPT}"
	fi
    fi
    TARLONGFLAGS="--file=${TARGET} ${TARLONGFLAGS}"    
    EXCLUDE="${TARGET} ${EXCLUDE}"
    for i in ${EXCLUDE}
    do
	# remove leading and trailing slash
	# i=`echo ${i} | sed -e 's/^\///' | sed -e 's/\/$//'`
	# remove leading and trailing "*" if any
	# i=`echo ${i} | sed -e 's/^\*//' | sed -e 's/\*$//'`
	# put them back in (pre-1.13.17 versions of tar may have this bug)
	# i="*"${i}"*"
	TARLONGFLAGS="--exclude=$i ${TARLONGFLAGS}"
    done
    printf "Comparing %s to %s...\n" "${FILES}" ${TARGET}
    TARCOMMAND="${TAR} ${TARLONGFLAGS} ${FILES}"
    _run
}

_restore()
{
    TARLONGFLAGS="--extract --preserve-permission"
    if [ "${OVERWRITE}" = false ]; then
	TARLONGFLAGS="--keep-old-files ${TARLONGFLAGS}"
    fi
    TARLONGFLAGS="--file=${FILENAME} ${TARLONGFLAGS}"
    if [ "${COMPRESS}" = true ]; then
	TARLONGFLAGS="--gunzip --file=${TARGET} ${TARLONGFLAGS}"
    else	
	if [ "${MULTIVOLUME}" = true ]; then
	    TARLONGFLAGS="${TARLONGFLAGS} --multi-volume --new-volume-script=${NEWVOLUMESCRIPT}"
	fi
    fi
    TARCOMMAND="${TAR} ${TARLONGFLAGS} ${FILES}"
    printf "Restoring %s from %s...\n" "${FILES}" ${FILENAME}
    _run 
}

_run()
{
    COMMANDSTRING="${TARCOMMAND}"
    if [ "${ZIPCOMMAND}" != "" ]; then
	COMMANDSTRING="${ZIPCOMMAND} | ""${COMMANDSTRING}"
    fi
    if [ "${TEST}" = true ]; then
	printf "Running ${COMMANDSTRING}\n"
	printf "This is only a test, *NO* files have been written\n"
    else
	if [ "${VERBOSE}" = true ]; then
	    printf "Running ${COMMANDSTRING}\n"
	fi
	if [ "${ZIPCOMMAND}" != "" ]; then
	    ${ZIPCOMMAND} | ${TARCOMMAND}
	    STATUS=$?
	else
	    ${TARCOMMAND}
	    STATUS=$?
	fi
	if [ ${STATUS} -ne 0 ]; then
	    printf "Command returned exit status ${STATUS}:\n"
#	    printf "${COMMANDSTRING}\n"
	else
	    printf "OK\n"
	fi
    fi
}

_prompt()
{
    printf "Finished inserting next disk and ready to continue? [y/n] "
    read ANSWER
    if [ "${ANSWER#[y|Y]}" = "${ANSWER}" ]; then
	exit 1
    fi
}

_setupRestore()
{
    _args $*
    set -- ${ARGS}
    if [ $# -lt 1 ]; then
	_usage
    fi
    FILENAME=$1
    shift
    FILES=$*
}

_setup()
{
    FILE=
    _args $*
    set -- ${ARGS}
    if [ $# -lt 1 ]; then
	_usage
    fi
    while [ $# -gt 0 ]
    do
	FILE=$1
	if [ "${LABELNAME}" = "" ]; then
	    LABELNAME=${FILE} # SET THE NAME OF THE ARCHIVE LABEL
	    # THE ARCHIVE LABEL NAME IS NOW SET
	    # THE FILENAME IS NOT YET SET
	    # PLEASE DON'T FORGET TO SET THE FILENAME CORRECTLY
	fi
	FILES="${FILES} ${FILE}"
	shift
    done
    if [ "${LABELNAME}" = "/" ]; then
	FILENAME="slash"
    else
	FILENAME=${LABELNAME}
#	nuke leading and trailing slash in each filename
	FILENAME=`echo ${FILENAME} | sed -e 's/^\///' | sed -e 's/\/$//'`
	FILENAME=`echo ${FILENAME} | sed -e 's/\//\./g'`
	echo filename: ${FILENAME}
    fi
    # remove trailing slash in volume (mountpoint) name
    VOLUME=`echo ${VOLUME} | sed -e 's/\/$//'`
    if [ "${BACKUPDIR}" != "" ]; then
	# remove leading and trailing slash in backup dir
	BACKUPDIR=`echo ${BACKUPDIR} | sed -e 's/^\///' | sed -e 's/\/$//'`
	BACKUPROOT=${VOLUME}/${BACKUPDIR}
    else
	BACKUPROOT=${VOLUME}
    fi
}

# Main
case "${PRGNAME}" in
    "kbackup")
	_setup $*
	_mount
	set -- ${ARGS}
	time _backup $*
	${UNMOUNT} ${VOLUME}
	${MOUNT} ${VOLUME}
	time _verify $*
	;;
    "verify")
	_setup $*
	_mount
	set -- ${ARGS}
	time _verify $*
	;;
    "restore")
	_setupRestore $*
	_mount
	set -- ${ARGS}
	time _restore $*
	;;
    "new-volume-script")
	${UNMOUNT} ${VOLUME}
	${EJECT}
	_prompt
	exit 0
	;;
    *)
	printf "This script must be called 'kbackup' or 'verify' or 'restore' or 'new-volume-script', exiting\n"
	exit 1
	;;
esac
if [ "${MOUNTED}" = false -o "${EJECT_WHEN_DONE}"=true ]; then
    ${UNMOUNT} ${VOLUME}
    if [ "${EJECT_WHEN_DONE}" = true ]; then
	${EJECT}
    fi
fi



Reply to: