From: Mark Wooding Date: Fri, 14 Dec 2012 23:06:10 +0000 (+0000) Subject: rsync-backup.8, rsync-backup.in: New dry-run mode for testing logic. X-Git-Tag: 1.0.0~15 X-Git-Url: https://git.distorted.org.uk/~mdw/rsync-backup/commitdiff_plain/3f496b2b1fb6cf3bf801074abb2c14c060a575bd rsync-backup.8, rsync-backup.in: New dry-run mode for testing logic. There's a tweak to retention policy coming up, and it turns out to be bad to test such things on one's production backups. --- diff --git a/rsync-backup.8 b/rsync-backup.8 index b36153a..20682ea 100644 --- a/rsync-backup.8 +++ b/rsync-backup.8 @@ -7,7 +7,7 @@ .TH rsync-backup 8 "7 October 2012" rsync-backup .SH SYNOPSIS .B rsync-backup -.RB [ \-v ] +.RB [ \-nv ] .RB [ \-c .IR config-file ] .SH DESCRIPTION @@ -73,6 +73,10 @@ in the .B \-V output). .TP +.B \-n +Don't actually take a backup, or write proper logs: instead, write a +description of what would be done to standard error. +.TP .B \-v Produce verbose progress information on standard output while the backup is running. This keeps one amused while running a backup diff --git a/rsync-backup.in b/rsync-backup.in index ade7231..292c6eb 100644 --- a/rsync-backup.in +++ b/rsync-backup.in @@ -35,6 +35,7 @@ fshashdir=@fshashdir@ conf=@sysconfdir@/rsync-backup.conf verbose=: +dryrun=nil ###-------------------------------------------------------------------------- ### Utility functions. @@ -57,26 +58,51 @@ do_rsync () { } log () { - now=$(date +"%Y-%m-%d %H:%M:%S %z") - echo >&9 "$now $*" + case $dryrun in + t) + echo >&2 " *** $*" + ;; + nil) + now=$(date +"%Y-%m-%d %H:%M:%S %z") + echo >&9 "$now $*" + ;; + esac +} + +maybe () { + ## Run CMD, if this isn't a dry run. + + case $dryrun in + t) echo >&2 " +++ $*" ;; + nil) "$@" ;; + esac } run () { tag=$1 cmd=$2; shift 2 ## Run CMD, logging its output in a pleasing manner. - log "BEGIN $tag" - rc=$( - { { { ( set +e - "$cmd" "$@" 3>&- 4>&- 5>&- 9>&- - echo $? >&5; ) | - while IFS= read line; do echo "| $line"; done >&4; } 2>&1 | - while IFS= read line; do echo "* $line"; done >&4; } 4>&1 | - cat >&9; } 5>&1 &2 " *** RUN $tag" + echo >&2 " +++ $cmd $*" + rc=0 + ;; + nil) + log "BEGIN $tag" + rc=$( + { { { ( set +e + "$cmd" "$@" 3>&- 4>&- 5>&- 9>&- + echo $? >&5; ) | + while IFS= read line; do echo "| $line"; done >&4; } 2>&1 | + while IFS= read line; do echo "* $line"; done >&4; } 4>&1 | + cat >&9; } 5>&1 &2 " --- keep $date" + ;; + EXPIRE,t) + echo >&2 " --- delete $date" + ;; + RETAIN,nil) echo "keep $date" ;; - EXPIRE) + EXPIRE,nil) echo "delete $date" $verbose -n " expire $date..." rm -rf $date $date.* @@ -530,7 +562,15 @@ do_backup () { while :; do ## Create and mount the remote snapshot. - snapmnt=$(snap_$snap $snapargs $fs $fsarg) || return $? + case $dryrun in + t) + maybe snap_$snap $fs $fsarg + snapmnt="" + ;; + nil) + snapmnt=$(snap_$snap $snapargs $fs $fsarg) || return $? + ;; + esac $verbose " create snapshot" ## Build the list of hardlink sources. @@ -541,8 +581,11 @@ do_backup () { done ## Copy files from the remote snapshot. - mkdir -p new/ - $verbose -n " running rsync..." + maybe mkdir -p new/ + case $dryrun in + t) $verbose " running rsync" ;; + nil) $verbose -n " running rsync..." ;; + esac set +e run "RSYNC of $host:$fs (snapshot on $snapmnt)" do_rsync \ $linkdests \ @@ -550,18 +593,21 @@ do_backup () { $snapmnt/ new/ rc_rsync=$? set -e - $verbose " done" + case $dryrun in nil) $verbose " done" ;; esac ## Collect a map of the snapshot for verification purposes. set +e - $verbose -n " remote fshash..." + case $dryrun in + t) $verbose " remote fshash" ;; + nil) $verbose -n " remote fshash..." ;; + esac run "@$host: fshash $fs" remote_fshash rc_fshash=$? set -e - $verbose " done" + case $dryrun in nil) $verbose " done" ;; esac ## Remove the snapshot. - unsnap_$snap $snapargs $fs $fsarg + maybe unsnap_$snap $snapargs $fs $fsarg $verbose " remove snapshot" ## If we failed to copy, then give up. @@ -572,11 +618,14 @@ do_backup () { esac ## Get a matching map of the files received. - mkdir -m750 -p $STOREDIR/tmp + maybe mkdir -m750 -p $STOREDIR/tmp/ localmap=$STOREDIR/tmp/fshash.$host.$fs.$date - $verbose -n " local fshash..." + case $dryrun in + t) $verbose " local fshash" ;; + nil) $verbose -n " local fshash..." ;; + esac run "local fshash $host:$fs" local_fshash || return $? - $verbose " done" + case $dryrun in nil) $verbose " done" ;; esac ## Compare the two maps. set +e @@ -599,27 +648,35 @@ do_backup () { done ## Glorious success. - rm -f $localmap + maybe rm -f $localmap $verbose " fshash match" ## Commit this backup. - backup_precommit_hook $host $fs $date - mv new $date - mv new.fshash $date.fshash - backup_commit_hook $host $fs $date - mkdir hack - ln -s $date hack/last - mv hack/last . - rmdir hack + case $dryrun in + nil) + backup_precommit_hook $host $fs $date + mv new $date + mv new.fshash $date.fshash + backup_commit_hook $host $fs $date + mkdir hack + ln -s $date hack/last + mv hack/last . + rmdir hack + ;; + esac $verbose " commit" ## Expire old backups. - case "${expire_policy+t}" in - t) run "expiry for $host:$fs" expire_backups ;; + case "${expire_policy+t},$dryrun" in + t,nil) run "expiry for $host:$fs" expire_backups ;; + t,t) expire_backups ;; esac ## Report success. - log "SUCCESSFUL BACKUP of $host:$fs" + case $dryrun in + t) log "END BACKUP of $host:$fs" ;; + nil) log "SUCCESSFUL BACKUP of $host:$fs" ;; + esac } backup () { @@ -648,19 +705,23 @@ backup () { ## Move to the store directory and set up somewhere to put this backup. cd $STOREDIR - if [ ! -d $host ]; then - mkdir -m755 $host - chown root:root $host - fi - if [ ! -d $host/$fs ]; then - mkdir -m750 $host/$fs - chown root:backup $host/$fs - fi + case $dryrun in + nil) + if [ ! -d $host ]; then + mkdir -m755 $host + chown root:root $host + fi + if [ ! -d $host/$fs ]; then + mkdir -m750 $host/$fs + chown root:backup $host/$fs + fi + ;; + esac cd $host/$fs ## Find out if we've already copied this filesystem today. date=$(date +%Y-%m-%d) - if [ -d $date ]; then + if [ $dryrun = nil ] && [ -d $date ]; then $verbose " already dumped" continue fi @@ -669,16 +730,23 @@ backup () { ## deleted old logs from today, so just checking for an unused sequence ## number is insufficient. Instead, check all of the logfiles for today, ## and use a sequence number that's larger than any of them. - seq=1 - for i in "$logdir/$host/$fs.$date#"*; do - tail=${i##*#} - case "$tail" in [!1-9]* | *[!0-9]*) continue ;; esac - if [ -f "$i" -a $tail -ge $seq ]; then seq=$(( tail + 1 )); fi - done - log="$logdir/$host/$fs.$date#$seq" + case $dryrun in + t) + log=/dev/null + ;; + nil) + seq=1 + for i in "$logdir/$host/$fs.$date#"*; do + tail=${i##*#} + case "$tail" in [!1-9]* | *[!0-9]*) continue ;; esac + if [ -f "$i" -a $tail -ge $seq ]; then seq=$(( tail + 1 )); fi + done + log="$logdir/$host/$fs.$date#$seq" + ;; + esac ## Do the backup of this filesystem. - mkdir -p $logdir/$host + case $dryrun in nil) mkdir -p $logdir/$host ;; esac if ! do_backup $date $fs $fsarg 9>$log 1>&9; then echo >&2 echo >&2 "$quis: backup of $host:$fs FAILED!" @@ -693,7 +761,7 @@ backup () { done ## If there are too many, go through and delete some early ones. - if [ $nlog -gt $MAXLOG ]; then + if [ $dryrun = nil ] && [ $nlog -gt $MAXLOG ]; then n=$(( nlog - MAXLOG )) for i in "$logdir/$host/$fs".*; do if [ ! -f "$i" ]; then continue; fi @@ -742,12 +810,13 @@ EOF whine () { echo >&8 "$@"; } -while getopts "hVvc:" opt; do +while getopts "hVvc:n" opt; do case "$opt" in h) usage; exit 0 ;; V) version; config; exit 0 ;; v) verbose=whine ;; c) conf=$OPTARG ;; + n) dryrun=t ;; *) exit 1 ;; esac done