From dd0fa2d4c32ea76a200bbd9a62691d4fd0f551ba Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Sat, 8 Dec 2012 18:42:37 +0100 Subject: initial import of rdumpfs, a rsync-based dump file system backup tool --- README | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rdumpfs | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 README create mode 100755 rdumpfs diff --git a/README b/README new file mode 100644 index 0000000..17119c6 --- /dev/null +++ b/README @@ -0,0 +1,94 @@ += rdumpfs, a rsync-based dump file system backup tool + +== Usage + +Run "rdumpfs SRC... DST" to create a daily backup of the SRC folders +at the rsync-target DST. SRC or DST can be local or remote addresses. +Only incremental changes against the last version use disk space, +unchanged files are hardlinked. + +Note that rdumpfs just wraps rsync, so the trailing slashes of SRC are +treated as in rsync: A trailing slash avoids creating an additional +directory level at the destination. + +To give you an idea, a example tree after running + rdumpfs /home /dump +on two days: + + /dump/ + 20121208/ + .rdumpfs.12312.log + home/ + chris/ + foo + delete_me_soon + ... + 20121209/ + .rdumpfs.98945.log + home/ + chris/ + foo -> hardlinked, same file as /dump/20121208/home/chris/foo + new + ... + +== Features + +* Only needs bash (or zsh) and rsync. +* Uses robust rsync command for all backup logic. +* Per-folder file ".rdumpfs" to configure exclusions (with possibly + additional variants). +* Never deletes files (except in the current backup, only if -f is + passed), clean up old dumps yourself. +* Backups can be resumed/updated (e.g. if you backed up a big file + accidentally today, you can just exclude it and re-run the backup.) +* Remote backup goes both ways: Remote systems can backup your files + ("pull"), or you can backup to remote systems ("push"). +* Easily hackable script, in case your needs are different from mine. + +== rsync options that may be useful together with rdumpfs + +* --fake-super to backup to non-root accounts +* --bwlimit so you don't clog your connection +* --partial to continue backups of big files +* --exclude for global excludes +* --dry-run to see what would happen + +== Why not use... + +Obviously, there are many similar scripts, among which I have used +dirvish and rsnapshot before writing rdumpfs for keeping daily dumps. + +* dirvish: Requires Perl with non-standard libraries. Cannot continue + partial backups. Complex configuration. No push backup. + +* rsnapshot: Requires Perl. No date-based directory naming. Obscure + configuration. No push backup. + +* pdumpfs: Requires Ruby. No special files. No remote backups. + +* rsync-incr: No push backup. + +* rdiff-backup: Requires Python. Old backups are not kept accessible in + the file system. + +* duplicity: Requires Python. Backups are not kept accessible in the + file system. + +* rsback: Requires Perl. No date-based directory naming. + +== When not use rdumpfs? + +* You want encrypted backups (try duplicity). +* You need incremental backups on a lower granularity than files (try + bup, vac, dar). +* Your target doesn't support hardlinks/SSH/rsync (try duplicity). +* You want automatic expiry (try dirvish). + +== Copyright + +rdumpfs is in the public domain. + +To the extent possible under law, the creator of this work has waived +all copyright and related or neighboring rights to this work. + +http://creativecommons.org/publicdomain/zero/1.0/ diff --git a/rdumpfs b/rdumpfs new file mode 100755 index 0000000..54225ed --- /dev/null +++ b/rdumpfs @@ -0,0 +1,49 @@ +#!/bin/bash +# rdumpfs - rsync-based dump file system backup tool +# Usage: rdumpfs [-f] [RSYNCOPT...] SRC [SRC...] DST +# -f: force potentially dangerous operations +# +# Written by Christian Neukirchen . +# rdumpfs is in the public domain. +# +# To the extent possible under law, the creator of this work has waived +# all copyright and related or neighboring rights to this work. +# http://creativecommons.org/publicdomain/zero/1.0/ + +fail() { + echo "$0: $1" 1>&2 + exit 111 +} + +force=false +[[ "$1" = -f ]] && force=true && shift + +src=("${@:1:$#-1}") +dst=${!#} + +now=$(date +%Y%m%d) +last=$(rsync $dst/ | cut -c44- | grep '^[0-9]*$' | sort -n | tail -1) + +rsync_args=(-aHAX --stats --human-readable + --out-format='%10l %n%L' --log-file-format='%10l %i %n%L' + --filter='dir-merge /.rdumpfs' --filter='protect .rdumpfs.*.log') +rsync_args+=(${VARIANT:+--filter='dir-merge /.rdumpfs.'$VARIANT}) + +if [[ -z "$last" ]]; then + $force || fail "no dump found, use -f on first dump." +else + rsync_args+=(--link-dest=../$last) +fi + +if [[ "$last" = "$now" ]]; then + $force || fail "dump $now exists, use -f to overwrite/update." + rsync_args+=(--delete-delay --delete-excluded) +fi + +LOGFILE=$(mktemp .rdumpfs.XXXXXXXX.log) +trap "rm -f $LOGFILE" INT QUIT TERM HUP EXIT + +rsync --log-file $LOGFILE "${rsync_args[@]}" "${src[@]}" "$dst/$now" +EC=$? +rsync $LOGFILE "$dst/$now/" +exit $EC -- cgit 1.4.1