#!/bin/bash # This software is the proprietary property of The Regents of the University of California ("The Regents") Copyright (c) # 1993-2006 The Regents of the University of California, Irvine campus. All Rights Reserved. # # Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # Neither the name of The Regents nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # The end-user understands that the program was developed for research # purposes and is advised not to rely exclusively on the program for any # reason. # # THE SOFTWARE PROVIDED IS ON AN "AS IS" BASIS, AND THE REGENTS AND # CONTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, # UPDATES, ENHANCEMENTS, OR MODIFICATIONS. THE REGENTS AND CONTRIBUTORS # SPECIFICALLY DISCLAIM ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE REGENTS OR # CONTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, # INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES, INCLUDING BUT NOT # LIMITED TO PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSE OF USE, # DATA OR PROFITS, OR BUSINESS INTERRUPTION, HOWEVER CAUSED AND UNDER ANY # THEORY OF LIABILITY WHETHER IN CONTRACT, STRICT LIABILITY OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. #et -x # On using rsync for really efficient backups: # http://www.mikerubel.org/computers/rsync_snapshots/ # On setting up a windows machine with an rsync daemon (service) : # http://www.gaztronics.net/rsync.php set -u export PATH=/bin:/usr/bin:/sbin:/usr/sbin USE_COMPRESSION=False RSYNC_OPTS="" VERBOSE=0 function usage { retval="$1" echo "Usage: $0" echo " --srcdir /src/dir" echo " --dstdir /dest/dir" echo " --num-to-keep 365" echo " --verbose" echo " --rsync-opts rsopts" echo " --use-compression" exit "$retval" } while [ "$#" -ge 1 ] do case "$1" in --rsync-opts) RSYNC_OPTS="$2" shift ;; --srcdir) SRCDIR="$2" shift ;; --dstdir) DSTDIR="$2" shift ;; --num-to-keep) NUM_TO_KEEP="$2" shift ;; --verbose) VERBOSE=$((VERBOSE+1)) ;; --use-compression) USE_COMPRESSION=True ;; --help|-h) usage 0 ;; *) echo "$0: Unrecognized option: $1" 1>&2 usage 1 ;; esac shift done bad=False if [ -z "${SRCDIR:-}" ] then echo Sorry, you must give a source directory with --srcdir bad=True fi if [ -z "${DSTDIR:-}" ] then echo Sorry, you must give a destination directory with --dstdir bad=True fi if [ -z "${NUM_TO_KEEP:-}" ] then echo Sorry, you must give a number of backups to retain with --num-to-keep bad=True fi case "$bad" in True) echo "$0: One or more required options not specified" 1>&2 usage 1 ;; False) ;; *) echo "$0: Internal error: \$bad not True or False: $bad" 1>&2 exit 1 ;; esac case "$USE_COMPRESSION" in True) COMPRESS_FLAG="-z" ;; False) COMPRESS_FLAG="" ;; *) echo "$0: Internal error: \$USE_COMPRESSION not True or False: $USE_COMPRESSION" 1>&2 exit 1 ;; esac if ! mkdir -p "$DSTDIR" then echo Sorry, mkdir -p "$DSTDIR" failed 1>&2 exit 1 fi if ! cd "$DSTDIR" then echo Sorry, cd "$DSTDIR" failed 1>&2 exit 1 fi if [ -d "backup.$NUM_TO_KEEP.complete" ] then # make room for some sliding, if the last directory already exists rm -rf "backup.$NUM_TO_KEEP.complete" fi if [ -d "backup.1.complete" ] then # slide them up a notch for backup_no in $(seq $((NUM_TO_KEEP-1)) -1 1) do if [ "$VERBOSE" -ge 1 ] then echo Checking backup "$backup_no"... fi if [ -d "backup.$backup_no.complete" ] then if [ "$VERBOSE" -ge 1 ] then echo Sliding backup "$backup_no"... fi backup_no_plus_1="$((backup_no+1))" mv "backup.$backup_no.complete" "backup.$backup_no_plus_1.complete" if [ -d "backup.$backup_no" ] then ( echo "Both backup.$backup_no and backup.$backup_no.complete detected" echo "Will keep backup.$backup_no.complete, but delete backup.$backup_no" ) 1>&2 rm -rf "backup.$backup_no" fi fi done if ! mkdir backup.1 then echo Sorry, mkdir backup.1 failed 1>&2 exit 1 fi elif [ -d backup.1 ] then ( echo "Incomplete backup detected - instead of sliding backups up a notch, instead" echo "we'll try to get a complete backup using the prior incomplete one as" echo "a starting point..." ) 1>&2 else if ! mkdir backup.1 then echo Sorry, mkdir backup.1 failed 1>&2 exit 1 fi fi move_it=False # shellcheck disable=SC2086 if rsync \ $RSYNC_OPTS \ -a \ $COMPRESS_FLAG \ --delete \ --link-dest=../backup.2.complete "$SRCDIR"/ backup.1 then move_it=True else case "$?" in 23) # This means some files gave permission denied - assume that's OK move_it=True ;; 24) # This means one or more files disappeared move_it=True ;; *) echo rsync failed, not "mv'ing. Exit code was $?" ;; esac fi case "$move_it" in True) mv backup.1 backup.1.complete ;; False) exit 1 ;; *) echo "$0: Internal error: \$move_it not True or False: $move_it" 1>&2 exit 1 ;; esac