Chris G <cl(a)isbd.net> wrote:
> Well here's my initial attempt at writing the incremental backup using
> rsync's --link-dest :-
> ...[weekly rotating backup script]
I got this going on my file server (not a NAS - it's a Debian box) using
the following script, which can be executed at any interval that seems
appropriate*, and retains a specified quantity of previous backups
rather than a time limited number. I find that so little changes between
backups that I can keep 100 of them on the same size backup media as the
main storage (1TB, ~60% full).
This should work in ash almost as-is, but you may need to use dc for the
maths (subtracting 1) instead of shell built-in capability:
TGT=`echo $BKP 1 -pq|dc`
Notes:
- This keeps the backup device mounted read-only unless a backup is
in progress, to avoid 'finger trouble' nuking important stuff.
- Uses the noatime option when mounted rw, to improve performance.
- Since this is a full file system backup, it excludes rather than
includes folders.
- It doesn't try to back up if there is <10G of free space on the
backup device (empirical determination, typically I see 10-20G
of change at worst per backup).
- Error messages (and debug) to stderr as this is run by cron so will
get emailed to root (me).
- Any issues are collected and stored in the backup folder.
Phil.
* - currently every 4 hours during the day but not overnight since the
machine may be busy using my free overnight bandwidth :)
----8<----
#! /bin/sh
# Take a snapshot of the current filesystem (minus snapshot folder and
caches)
#DBG=--verbose
BACKUP_DEV="UUID=go-look-in-dev-disk-by-uuid-xxxxxxxxxxxx"
BACKUP_DIR=/var/backups/snapshot
EXCLUDES="/dev /proc /sys /mnt /media /tmp /var/cache /var/lock \
/var/www/.get_iplayer $BACKUP_DIR"
# Time/date records
BKSTART=`date`
# Only keep up to 100 snapshots
MAX_BACKUP=100
# 10GB in k
MIN_SPACE_K=10000000
docmd() {
[ -n "$DBG" ] && echo debug: "$*" >&2
$*
}
NEED_REMOUNT=
remount() {
docmd mount -o remount,ro $BACKUP_DEV $BACKUP_DIR
}
barf() {
echo "$*" >&2
[ -n "$NEED_REMOUNT" ] && remount
exit 1
}
# Mount the snapshot folder read-write
docmd mount -o remount,rw,noatime $BACKUP_DEV $BACKUP_DIR
[ $? -eq 0 ] || barf "unable to remount $BACKUP_DIR rw"
NEED_REMOUNT=1
# Space check
docmd cd $BACKUP_DIR
AVAIL=`df -k . |tail -1 |(read d b u a t; echo $a)`
[ $AVAIL -gt $MIN_SPACE_K ] || barf "out of backup device space"
[ -n "$DBG" ] && echo "debug: available space: ${AVAIL}k" >&2
# Rotate existing backups
[ -d backup.$MAX_BACKUP ] && docmd rm -rf backup.$MAX_BACKUP
BKP=$MAX_BACKUP
while [ $BKP -gt 0 ]
do
TGT=$(($BKP-1))
[ -d backup.$TGT ] && docmd mv backup.$TGT backup.$BKP
BKP=$TGT
done
# rsync changes into fresh backup, hard-linking unchanged files
for p in $EXCLUDES
do
echo $p >>/tmp/backup-excludes.$$
done
docmd rsync $DBG -a --link-dest=$BACKUP_DIR/backup.1
--exclude-from=/tmp/backup-excludes.$$ / $BACKUP_DIR/backup.0
>/tmp/sync-log.$$ 2>&1
if [ $? -ne 0 ]; then
echo "rsync into $BACKUP_DIR had some problems, see log" >&2
docmd mv /tmp/sync-log.$$ $BACKUP_DIR/backup.0/RSYNC.LOG
fi
docmd rm -f /tmp/backup-excludes.$$ /tmp/sync-log.$$
# Time/date records
BKSTOP=`date`
docmd echo "Backup started: $BKSTART, completed: $BKSTOP"
>$BACKUP_DIR/backup.0/README.DATES
# Remount read-only
NEED_REMOUNT=
remount
[ $? -eq 0 ] || barf "unable to remount $BACKUP_DIR ro"