|
|
| Zeile 1: |
Zeile 1: |
| − | #!/bin/bash
| + | tbd |
| − | # ----------------------------------------------------------------------
| |
| − | ## (c) 2007, Pfalzwolf for www.linux-club.de
| |
| − | ## Idea:
| |
| − | ## Mike Rubel 2004.01.04
| |
| − | ##
| |
| − | ## License:
| |
| − | ## use this software on your own risk, it works for me but there
| |
| − | ## are no guaranties at all
| |
| − | ## ----------------------------------------------
| |
| − | ##
| |
| − | ## make_snapshot:
| |
| − | ## Backup Script based on rsync
| |
| − | ## It creates Generation Backups for the levels daily, weekly and montly
| |
| − | ##
| |
| − | ## Version:
| |
| − | ## 0.3
| |
| − | ##
| |
| − | ## Synopsis:
| |
| − | ## make_snapshot [OPTIONS]
| |
| − | ##
| |
| − | ## Description:
| |
| − | ## This script was adopted from Mike Rubels documentation from
| |
| − | ## http://www.mikerubel.org/computers/rsync_snapshots/
| |
| − | ## Based on Mikes handy rotating-filesystem-snapshot utility.
| |
| − | ## The basic idea is it makes rotating backup-snapshots of /home whenever called
| |
| − | ## A few elements came from
| |
| − | ## http://www.heinlein-support.de/web/support/wissen/rsync-backup/
| |
| − | ## An exclude list avoids to backup superflous files.
| |
| − | ##
| |
| − | ## Changes:
| |
| − | ## Instead of hourly, daily and weekly snapshots, daily, weekly and monthly
| |
| − | ## snapshots are used.
| |
| − | ## Checking the available space on backup media
| |
| − | ## Free configurable number of snapshots for every single level
| |
| − | ## Everything packed into one script
| |
| − | ##
| |
| − | ## Options:
| |
| − | ## -d make the daily backup plus rotate
| |
| − | ## -w make the weekly backup
| |
| − | ## -m make the monthly backup
| |
| − | ## -h displays a short help text
| |
| − | ##
| |
| − | ## Changelog:
| |
| − | ## --------
| |
| − | ########################################################################
| |
| − | | |
| − | unset PATH # suggestion from H. Milz: avoid accidental use of $PATH
| |
| − | | |
| − | # ------------- System Commands used by this script --------------------
| |
| − | ID=/usr/bin/id;
| |
| − | ECHO=/bin/echo;
| |
| − | MOUNT=/bin/mount;
| |
| − | RM=/bin/rm;
| |
| − | MV=/bin/mv;
| |
| − | CP=/bin/cp;
| |
| − | TOUCH=/bin/touch;
| |
| − | RSYNC=/usr/bin/rsync;
| |
| − | DF=/bin/df;
| |
| − | TAIL=/usr/bin/tail;
| |
| − | SED=/bin/sed;
| |
| − | SYNC=/bin/sync;
| |
| − | LOGGER=/bin/logger;
| |
| − | CHMOD=/bin/chmod;
| |
| − | MKDIR=/bin/mkdir;
| |
| − | | |
| − | # ======================= CUSTOMIZING SECTION ==========================
| |
| − | MOUNT_DEVICE=/dev/sda2; # Your Mount device
| |
| − | MOUNT_RO=false; # For write protection set to true
| |
| − | SNAPSHOT_RW=/DASI/TEST; # where to store the backups
| |
| − | EXCLUDES=/home/wolf/nobackup/backup_exclude; # Create the backup_exclude file first!
| |
| − | CHECK_HDMINFREE=true; # Check free space
| |
| − | HDMINFREE=93; # Make a backup up to this percentage
| |
| − | DAYS=3; # Number of daily backups -1
| |
| − | WEEKS=2; # Number of weekly backups -1
| |
| − | MONTHS=3; # Number of monthly backups -1
| |
| − | # ======================================================================
| |
| − | | |
| − | # Make sure we're running as root
| |
| − | if (( `$ID -u` != 0 )); then { $ECHO "Sorry, must be root. Exiting..."; exit; } fi
| |
| − | | |
| − | # Check Argument
| |
| − | if [ $# != 1 ] ; then { $ECHO "Error: Wrong number of arguments. \
| |
| − | Vaild is one out of -d, -w, -m, -h" ; exit; } fi
| |
| − | | |
| − | # Check Customization
| |
| − | if ! [ -b $MOUNT_DEVICE ] ; then { $ECHO "Error: Mount device $EXCLUDES isn't valid" ; exit; } fi
| |
| − | if ! [ -d $SNAPSHOT_RW ] ; then
| |
| − | { $ECHO "Error: Backup Directory $SNAPSHOT_RW missing"; exit; } fi
| |
| − | if ! [ -d $SNAPSHOT_RW/home ] ; then $MKDIR -p $SNAPSHOT_RW/home; fi
| |
| − | if ! [ -f $EXCLUDES ] ; then { $ECHO "Error: Exclude File $EXCLUDES missing" ; exit; } fi
| |
| − | | |
| − | # Check free space on disk
| |
| − | GETPERCENTAGE='s/.* \([0-9]\{1,3\}\)%.*/\1/';
| |
| − | if $CHECK_HDMINFREE ; then
| |
| − | KBISFREE=`$DF /$SNAPSHOT_RW | $TAIL -n1 | $SED -e "$GETPERCENTAGE"`
| |
| − | if [ $KBISFREE -ge $HDMINFREE ] ; then
| |
| − | $ECHO "Error: Not enough space left for rotating backups!"
| |
| − | $LOGGER "Error: Not enough space left for rotating backups!"
| |
| − | exit
| |
| − | fi
| |
| − | fi
| |
| − | | |
| − | # ------------- The Script itself --------------------------------------
| |
| − | | |
| − | if $MOUNT_RO ; then
| |
| − | # Attempt to remount the RW mount point as RW; else abort
| |
| − | $MOUNT -o remount,rw $MOUNT_DEVICE $SNAPSHOT_RW ;
| |
| − | if (( $? )); then
| |
| − | $ECHO "Error: could not remount $SNAPSHOT_RW readwrite";
| |
| − | exit;
| |
| − | fi;
| |
| − | fi;
| |
| − | | |
| − | | |
| − | case $1 in
| |
| − | # *********** Daily Backups ********************************************
| |
| − | -d | -D) $ECHO "Starting Daily Backup..."
| |
| − | # Rotating daily snapshots of /home
| |
| − | | |
| − | # Step 1: Delete the oldest snapshot, if it exists:
| |
| − | # It is NOT moved to the weekly backups level since you can make hundreds of daily backups
| |
| − | if [ -d $SNAPSHOT_RW/home/daily.$DAYS ] ; then
| |
| − | $RM -rf $SNAPSHOT_RW/home/daily.$DAYS ;
| |
| − | fi;
| |
| − | | |
| − | # Step 2: Shift all other snapshots(s) by one, if they exist (e.g. 6->7...1->2)
| |
| − | OLD=$DAYS;
| |
| − | while [ $OLD -ge 2 ] ; do
| |
| − | OLD=$[$OLD-1]
| |
| − | if [ -d $SNAPSHOT_RW/home/daily.$OLD ] ; then
| |
| − | NEW=$[ $OLD + 1 ]
| |
| − | # Save date
| |
| − | $TOUCH $SNAPSHOT_RW/.timestamp -r $SNAPSHOT_RW/home/daily.$OLD
| |
| − | $MV $SNAPSHOT_RW/home/daily.$OLD $SNAPSHOT_RW/home/daily.$NEW
| |
| − | # Restore date
| |
| − | $TOUCH $SNAPSHOT_RW/home/daily.$NEW/.timestamp \
| |
| − | -r $SNAPSHOT_RW/.timestamp
| |
| − | fi;
| |
| − | done
| |
| − | | |
| − | # Step 3: make a hard-link-only (except for dirs) copy of the latest snapshot,
| |
| − | # If that exists 0->1
| |
| − | if ! [ -d $SNAPSHOT_RW/home/daily.0 ] ; then
| |
| − | $MKDIR -p $SNAPSHOT_RW/home/daily.0
| |
| − | $TOUCH $SNAPSHOT_RW/home/daily.0/.timestamp
| |
| − | else
| |
| − | $CP -al $SNAPSHOT_RW/home/daily.0 $SNAPSHOT_RW/home/daily.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!
| |
| − | $RSYNC \
| |
| − | -va --delete --delete-excluded \
| |
| − | --exclude-from="$EXCLUDES" \
| |
| − | /home/ $SNAPSHOT_RW/home/daily.0 ;
| |
| − | | |
| − | # Check return code
| |
| − | # 0 = ok,
| |
| − | # 24 is also ok. It appears if files were changed or deleted while this script runs
| |
| − | # Other return codes are Error -- see man (1) rsync
| |
| − | if ! [ $? = 24 -o $? = 0 ] ; then
| |
| − | $ECHO "Error: rsync finished on $MOUNT_DEVICE with errors!"
| |
| − | $LOGGER "Error: rsync finished on $MOUNT_DEVICE with errors!"
| |
| − | fi;
| |
| − | | |
| − | # Step 5: update the mtime of daily.0 to reflect the snapshot time
| |
| − | $TOUCH $SNAPSHOT_RW/home/daily.0 ;
| |
| − | | |
| − | # Finished!
| |
| − | $ECHO "Finished rsync backup on $MOUNT_DEVICE..."
| |
| − | $LOGGER "Finished rsync backup on $MOUNT_DEVICE..."
| |
| − | | |
| − | # For beeing on the secure site...
| |
| − | $SYNC;;
| |
| − | | |
| − | # And thats it for home.
| |
| − | | |
| − | # *********** Weekly Backup ********************************************
| |
| − | -w | -W)$ECHO "Starting Weekly Backup..."
| |
| − |
| |
| − | # Step 1: Delete the oldest snapshot, if it exists
| |
| − | if [ -d $SNAPSHOT_RW/home/weekly.$WEEKS ] ; then
| |
| − | $RM -rf $SNAPSHOT_RW/home/weekly.$WEEKS ;
| |
| − | fi;
| |
| − |
| |
| − | # Step 2: shift the middle snapshots(s) by one, if they exist 3->4 ..0->1
| |
| − | OLD=$WEEKS;
| |
| − | while [ $OLD -ge 1 ] ; do
| |
| − | OLD=$[$OLD-1]
| |
| − | if [ -d $SNAPSHOT_RW/home/weekly.$OLD ] ; then
| |
| − | NEW=$[ $OLD + 1 ]
| |
| − | $MV $SNAPSHOT_RW/home/weekly.$OLD $SNAPSHOT_RW/home/weekly.$NEW ;
| |
| − | fi;
| |
| − | done
| |
| − | | |
| − | # Step 3: Make a hard-link-only (except for dirs) copy of
| |
| − | # daily.(max), assuming that exists, into weekly.0
| |
| − | if [ -d $SNAPSHOT_RW/home/daily.$DAYS ] ; then
| |
| − | $CP -al $SNAPSHOT_RW/home/daily.$DAYS $SNAPSHOT_RW/home/weekly.0 ;
| |
| − | fi;;
| |
| − | | |
| − | # *********** Monthly Backup *******************************************
| |
| − | -m | -M)$ECHO "Starting Monthly Backup..."
| |
| − |
| |
| − | # Step 1: Delete the oldest snapshot, if it exists
| |
| − | if [ -d $SNAPSHOT_RW/home/monthly.$MONTHS ] ; then
| |
| − | $RM -rf $SNAPSHOT_RW/home/monthly.$MONTHS ;
| |
| − | fi;
| |
| − |
| |
| − | # Step 2: Shift the middle snapshots(s) by one, if they exist 6->7 ..0->1
| |
| − | OLD=$MONTHS;
| |
| − | while [ $OLD -ge 1 ] ; do
| |
| − | OLD=$[$OLD-1]
| |
| − | if [ -d $SNAPSHOT_RW/home/monthly.$OLD ] ; then
| |
| − | NEW=$[ $OLD + 1 ]
| |
| − | $MV $SNAPSHOT_RW/home/monthly.$OLD $SNAPSHOT_RW/home/monthly.$NEW ;
| |
| − | fi;
| |
| − | done
| |
| − | | |
| − | # Step 3: Make a hard-link-only (except for dirs) copy of
| |
| − | # weekly.(max), assuming that exists, into monthly.0
| |
| − | if [ -d $SNAPSHOT_RW/home/weekly.$WEEKS ] ; then
| |
| − | $CP -al $SNAPSHOT_RW/home/weekly.$WEEKS $SNAPSHOT_RW/home/monthly.0 ;
| |
| − | fi;;
| |
| − | | |
| − | -h | -H)$ECHO "Usage:
| |
| − | make_snapshot -d Initiates daily backup
| |
| − | make_snapshot -w Initiates weekly backup
| |
| − | make_snapshot -m Initiates monthly backup
| |
| − | make_snapshot -h Displays this text."; exit;;
| |
| − |
| |
| − | *) $ECHO "Error: Wrong argument. Vaild is one out of -d, -w, -m, -h" ; exit;;
| |
| − | | |
| − | esac
| |
| − | | |
| − | $ECHO "Backup ended"
| |
| − | if $MOUNT_RO ; then
| |
| − | # Now remount the RW snapshot mountpoint as readonly
| |
| − | $MOUNT -o remount,ro $MOUNT_DEVICE $SNAPSHOT_RW ;
| |
| − | if (( $? )); then
| |
| − | $ECHO "Error: Could not remount $SNAPSHOT_RW readonly";
| |
| − | exit;
| |
| − | fi;
| |
| − | fi;
| |