#!/bin/bash # # Cmdline arguments, and they must be in order: # # 1: The name of the folder, and only the folder. # If you want /var/spool/mail you write mail here. # # 2: Remote parent folder, with final /. # E.g. root@remote.host:/var/spool/ # Or rsync://remote.host/var/spool/ # Or just /var/spool/ if local to local backup. # # 3: Parent folder to store the backup, again with /. # E.g. /backup/ # # 4: Number of increments to keep. Defaults to 4. # # Examples: # /usr/bin/incremental.sh mail root@hostname:/var/spool/ /backup/hostname/ 7 # /usr/bin/incremental.sh home root@hostname:/ /backup/hostname/ 7 # /usr/bin/incremental.sh etc rsync://hostname/ /backup/hostname/ 7 # # The script will exclude files based on an exclude.x file in rsync format. # In the above home example the exclude file should be: # /backup/hostname/exclude.home # # Going from the home example, the directory structure would after a few # iterations look akin to: # /backup/homename/home.0/ # /backup/homename/home.1/ # /backup/homename/home.2/ # /backup/homename/home.std.log.0 # /backup/homename/home.std.log.1 # /backup/homename/home.std.log.2 # /backup/homename/home.err.log.0 # /backup/homename/home.err.log.1 # /backup/homename/home.err.log.2 # /backup/homename/exclude.home # let LEVELS="$4"+0 if [ "$LEVELS" -le "0" ] then LEVELS=4 fi # If target folder doesn't exist, create it. if [ ! -d "$3" ] then mkdir -p "$3" if [ ! -d "$3" ] then echo "Couldn't create $3!" exit fi chmod 0700 "$3" fi cd "$3" if [ ! -f "exclude.$1" ] then touch "exclude.$1" chmod 0600 "exclude.$1" fi # If there is a .0 level, shuffle all levels down one if [ -d "$1.0" ] then if [ -d "$1.$LEVELS" ] then rm -rf "$1.$LEVELS" fi if [ -f "$1.std.log.$LEVELS" ] then rm -f "$1.std.log.$LEVELS" fi if [ -f "$1.err.log.$LEVELS" ] then rm -f "$1.err.log.$LEVELS" fi for ((a=$LEVELS-1,b=$LEVELS ; a>=0 ; a--,b--)) do if [ -d "$1.$a" ] then mv "$1.$a" "$1.$b" fi if [ -f "$1.std.log.$a" ] then mv "$1.std.log.$a" "$1.std.log.$b" fi if [ -f "$1.err.log.$a" ] then mv "$1.err.log.$a" "$1.err.log.$b" fi done fi # Capture all output from here on to the specific logs { if [ -d "$1.1" ] then # If the .1 level exists, consider it the most recent to link against rsync -azSvy --partial "--exclude-from=exclude.$1" --numeric-ids --delete --delete-excluded "--link-dest=../$1.1" "$2$1/" "$1.0/" else # If it doesn't exist, make a full copy into .0 rsync -azSvy --partial "--exclude-from=exclude.$1" --numeric-ids --delete --delete-excluded "$2$1/" "$1.0/" fi } > "$1.std.log.0" 2> "$1.err.log.0"