#!/bin/bash # ---------------------------------------------------------------------- # (boglin:)based almost entirely on code by mrubel from: # (boglin:)The only really important thing I added is a pretend option. # mikes handy rotating-filesystem-snapshot utility # http://www.mikerubel.org/computers/rsync_snapshots/ # thanks to anme for the link, additions are commented. # ---------------------------------------------------------------------- # this needs to be a lot more general, but the basic idea is it makes # rotating backup-snapshots of / to $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.n # whenever called # ---------------------------------------------------------------------- # -------------(boglin:) general settings ------------------------------ #The 'name' of this rotating backup, becomes subdirectory under $SNAPSHOT_RW BU_NAME="Gentoo-1.4/rsync" #The number of copies to keep BU_DEPTH=3 #The type of backup, ie: if run fron cron.daily; set to daily BU_TYPE="daily" #The excludes I choose (why not make them default?) L_EXCLUDES="/dev /mnt /tmp /usr/portage/distfiles /var/tmp /proc /home /usr/scr/linux-* tmp/" # ------------- file locations ----------------------------------------- # (boglin:)mrubel reccommends that all users have read-only access to the # back up filesystem through a local nfs share, can also be accomplished # with smb, but you shouldn't let anything write to the back up fs at all, # except when this script is run. :) MOUNT_DEVICE=/dev/hde1 SNAPSHOT_RW=/mnt/BU # ------------- the script itself -------------------------------------- L_P="" Rotate() { # make sure we're running as root if (( `id -u` != 0 )); then { echo "Sorry, must be root. Exiting..."; exit; } fi # attempt to remount the RW mount point as RW; else abort mount -o remount,rw $MOUNT_DEVICE $SNAPSHOT_RW ; if (( $? )); then { echo "snapshot: could not remount $SNAPSHOT_RW readwrite"; exit; } fi; # step 1: delete the oldest snapshot, if it exists: if [ -d $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.$BU_DEPTH ] ; then rm -rf $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.$BU_DEPTH ; fi ; #(boglin:) rotating snapshots of /$BU_NAME (fixme: this should be more general) # fix: (BG) Use 'seq' for a C-like loop. for i in `seq $BU_DEPTH -1 2`; do # step 2: shift the middle snapshots(s) back by one, if they exist if [ -d $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.$(($i - 1)) ] ; then mv $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.$(($i - 1)) $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.$i ;\ fi; done # step 3: make a hard-link-only (except for dirs) copy of the latest snapshot, # if that exists if [ -d $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0 ] ; then cp -al $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0 $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.1 ;\ fi; # step 4: rsync from the system into the latest snapshot (notice # that # rsync behaves like cp --remove-destination by default, so the destination # is unlinked first. If it were not so, this would copy over the # other # snapshot(s) too! if [ ! -d $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0 ] ; then if [ -f $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0 ] ; then rm $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0;\ fi; mkdir $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0;\ fi; L_P="" } #end Rotate Doit() { #(boglin:) Build $EXCLUDES EXCLUDES="" for arg in $L_EXCLUDES; do EXCLUDES="$EXCLUDES--exclude=$arg " done pushd / > /dev/null rsync $L_P-va --delete-excluded $EXCLUDES . $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0/ ; popd > /dev/null # step 5: update the mtime of $BU_TYPE.0 to reflect the snapshot # time touch $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0 ; } Cleanup() { # now remount the RW snapshot mountpoint as readonly mount -o remount,ro $MOUNT_DEVICE $SNAPSHOT_RW ; if (( $? )); then { echo "snapshot: could not remount $SNAPSHOT_RW readonly"; exit; } fi; } Usage() # Prints some help { echo echo "############## make_snapshot help #####################" echo echo "This script will clone your gentoo root partition to $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.#'s " echo "Edit this script to configure levels and locations. Usage:" echo "make_snapshot [-ph]" echo " -h: show this message." echo " -p: pretend mode (passes -n to rsync)" } #Entry case "$#" in 0) echo "Begining backup of / to $SNAPSHOT_RW/$BU_NAME/$BU_TYPE.0" echo "If you haven't edited this script to you liking I suggest you ^C and do so now." Rotate Doit Cleanup echo "Finished backup of /" exit 0 ;; 1) case "$1" in -p) L_P="-n " Doit exit 0 ;; -h) Usage exit 0 ;; *) echo echo "Unknown parameter..." echo Usage exit 1 ;; esac ;; esac ;;