rsync script for snapshot backups

Petros Angelatos petrosagg at gmail.com
Wed Jun 22 05:14:26 UTC 2016


On 19 June 2016 at 10:27, Simon Hobson <linux at thehobsons.co.uk> wrote:
> Dennis Steinkamp <dennis at lightandshadow.tv> wrote:
>
>> i tried to create a simple rsync script that should create daily backups from a ZFS storage and put them into a timestamp folder.
>> After creating the initial full backup, the following backups should only contain "new data" and the rest will be referenced via hardlinks (-link-dest)
>> ...
>> Well, it works but there is a huge flaw with his approach and i am not able to solve it on my own unfortunately.
>> As long as the backups are finishing properly, everything is fine but as soon as one backup job couldn`t be finished for some reason, (like it will be aborted accidently or a power cut occurs)
>> the whole backup chain is messed up and usually the script creates a new full backup which fills up my backup storage.
>
> Yes indeed, this is a typical flaw with many systems - you often need to throw away the partial backup.
> One option that comes to mind is this :
> Create the new backup in a directory called (for example) "new" or "in-progress". If, and only if, the backup completes, then rename this to a timestamp. If when you start a new backup, if the in-progress folder exists, then use that and it'll be freshened to the current source state.

I have an extremely similar script for my backups and that's exactly
what I do to deal with backups that are stopped mid-way, either by
power failures or by me. I rsync to a .tmp-$target directory, where
$target is what I'm backing up. I have separate backups for my rootfs
and /home. I also start the whole thing under ionice so that my
computer doesn't get slow from all this I/O. Lastly, before renaming
the .tmp-$target to the final directory I do a `sync -f` because rsync
doesn't seem to call fsync() when copying files and you can have a
failed backup if a power failure happens after the rename().

Here is my script:

#!/bin/bash

set -o errexit
set -o pipefail

target=$1

case "$target" in
    home)
        source=/home
        ;;
    root)
        source=/
        ;;
esac

PATHTOBACKUP=/root/backup

date=$(date --utc "+%Y-%m-%dT%H:%M:%S")

ionice --class 3 rsync \
    --archive \
    --verbose \
    --one-file-system \
    --sparse \
    --delete \
    --compress \
    --log-file=$PATHTOBACKUP/.tmp-$target.log \
    --link-dest=$PATHTOBACKUP/$target-current \
    $source $PATHTOBACKUP/.tmp-$target

sync -f $PATHTOBACKUP/.tmp-$target

mv $PATHTOBACKUP/.tmp-$target.log $PATHTOBACKUP/$target-$date.log
mv $PATHTOBACKUP/.tmp-$target $PATHTOBACKUP/$target-$date

ln --symbolic --force --no-dereference $target-$date
$PATHTOBACKUP/$target-current



More information about the rsync mailing list