chiark / gitweb /
rsync-backup.in, rsync-backup.8: Retry backups which fail fshash check.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 19 Oct 2012 08:46:31 +0000 (09:46 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 19 Oct 2012 08:46:31 +0000 (09:46 +0100)
I'm getting annoyed with vampire:root failing in the morning and then
succeeding after a manual retry.  So get the script to retry automatically.

rsync-backup.8
rsync-backup.in

index a265352ced5ebf5c1f3c36ea754784a0ced56d9b..b36153a2def9f3a4f29da86b6aa82caf3f09c56f 100644 (file)
@@ -194,11 +194,28 @@ Expiry considers each existing dump against the policy lines in order:
 the last applicable line determines the dump's fate \(en so you should
 probably write the lines in decreasing order of duration.
 .TP
+.BI "retry " count
+The
+.B live
+snapshot type (see below) doesn't prevent a filesystem from being
+modified while it's being backed up.  If this happens, the
+.B fshash
+pass will detect the difference and fail.  If the filesystem in question
+is relatively quiescent, then maybe retrying the backup will result in a
+successful consistent copy.  Following this command, a backup which
+results in an
+.B fshash
+mismatch will be retried up to
+.I count
+times before being declared a failure.
+.TP
 .BI "snap " type " " \fR[\fIargs\fR...]
 Use the snapshot
 .I type
 for subsequent backups.  Some snapshot types require additional
-arguments, which may be supplied here.
+arguments, which may be supplied here.  This command clears the
+.B retry
+counter.
 .SS Configuration variables
 The following shell variables may be overridden by the configuration
 file.
index 705696d2b8cb4f73461c9f8aa288177d48c84d8c..ade72316736378a6b1551c0ed7286b91aada6ede 100644 (file)
@@ -521,62 +521,84 @@ do_backup () {
   ## Back up FS on the current host.
 
   set -e
+  attempt=0
 
   ## Report the start of this attempt.
   log "START BACKUP of $host:$fs"
 
-  ## Create and mount the remote snapshot.
-  snapmnt=$(snap_$snap $snapargs $fs $fsarg) || return $?
-  $verbose "   create snapshot"
+  ## Maybe we need to retry the backup.
+  while :; do
 
-  ## Build the list of hardlink sources.
-  linkdests=""
-  for i in $host $like; do
-    d=$STOREDIR/$i/$fs/last/
-    if [ -d $d ]; then linkdests="$linkdests --link-dest=$d"; fi
-  done
+    ## Create and mount the remote snapshot.
+    snapmnt=$(snap_$snap $snapargs $fs $fsarg) || return $?
+    $verbose " create snapshot"
 
-  ## Copy files from the remote snapshot.
-  mkdir -p new/
-  $verbose -n "        running rsync..."
-  set +e
-  run "RSYNC of $host:$fs (snapshot on $snapmnt)" do_rsync \
-    $linkdests \
-    $rsyncargs \
-    $snapmnt/ new/
-  rc_rsync=$?
-  set -e
-  $verbose " done"
+    ## Build the list of hardlink sources.
+    linkdests=""
+    for i in $host $like; do
+      d=$STOREDIR/$i/$fs/last/
+      if [ -d $d ]; then linkdests="$linkdests --link-dest=$d"; fi
+    done
 
-  ## Collect a map of the snapshot for verification purposes.
-  set +e
-  $verbose -n "        remote fshash..."
-  run "@$host: fshash $fs" remote_fshash
-  rc_fshash=$?
-  set -e
-  $verbose " done"
+    ## Copy files from the remote snapshot.
+    mkdir -p new/
+    $verbose -n "      running rsync..."
+    set +e
+    run "RSYNC of $host:$fs (snapshot on $snapmnt)" do_rsync \
+      $linkdests \
+      $rsyncargs \
+      $snapmnt/ new/
+    rc_rsync=$?
+    set -e
+    $verbose " done"
 
-  ## Remove the snapshot.
-  unsnap_$snap $snapargs $fs $fsarg
-  $verbose "   remove snapshot"
+    ## Collect a map of the snapshot for verification purposes.
+    set +e
+    $verbose -n "      remote fshash..."
+    run "@$host: fshash $fs" remote_fshash
+    rc_fshash=$?
+    set -e
+    $verbose " done"
 
-  ## If we failed to copy, then give up.
-  case $rc_rsync:$rc_fshash in
-    0:0) ;;
-    0:*) return $rc_fshash ;;
-    *) return $rc_rsync ;;
-  esac
+    ## Remove the snapshot.
+    unsnap_$snap $snapargs $fs $fsarg
+    $verbose " remove snapshot"
 
-  ## Get a matching map of the files received.
-  mkdir -m750 -p $STOREDIR/tmp
-  localmap=$STOREDIR/tmp/fshash.$host.$fs.$date
-  $verbose -n "        local fshash..."
-  run "local fshash $host:$fs" local_fshash || return $?
-  $verbose " done"
+    ## If we failed to copy, then give up.
+    case $rc_rsync:$rc_fshash in
+      0:0) ;;
+      0:*) return $rc_fshash ;;
+      *) return $rc_rsync ;;
+    esac
+
+    ## Get a matching map of the files received.
+    mkdir -m750 -p $STOREDIR/tmp
+    localmap=$STOREDIR/tmp/fshash.$host.$fs.$date
+    $verbose -n "      local fshash..."
+    run "local fshash $host:$fs" local_fshash || return $?
+    $verbose " done"
+
+    ## Compare the two maps.
+    set +e
+    run "compare fshash maps for $host:$fs" diff -u new.fshash $localmap
+    rc_diff=$?
+    set -e
+    case $rc_diff in
+      0)
+       break
+       ;;
+      1)
+       if [ $attempt -ge $retry ]; then return $rc; fi
+       $verbose "      fshash mismatch; retrying"
+       attempt=$(( $attempt + 1 ))
+       ;;
+      *)
+       return $rc_diff
+       ;;
+    esac
+  done
 
-  ## Compare the two maps.
-  run "compare fshash maps for $host:$fs" \
-    diff -u new.fshash $localmap || return $?
+  ## Glorious success.
   rm -f $localmap
   $verbose "   fshash match"
 
@@ -687,9 +709,10 @@ backup () {
 ### Configuration functions.
 
 host () { host=$1; like=; $verbose "host $host"; }
-snaptype () { snap=$1; shift; snapargs="$*"; }
+snaptype () { snap=$1; shift; snapargs="$*"; retry=0; }
 rsyncargs () { rsyncargs="$*"; }
 like () { like="$*"; }
+retry () { retry="$*"; }
 
 retain () {
   expire_policy="${expire_policy+$expire_policy