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