tons of misc updates
[distro-setup] / btrbk-run
index a1c6963a926b445454ca1d27634a56737e2d34da..0d680283b44135981748e0f5a49595a7c9db21bd 100755 (executable)
--- a/btrbk-run
+++ b/btrbk-run
@@ -15,6 +15,7 @@
 
 
 # todo: remove old leaf subvols, like keep up to 1 month or something.
+# todo: if we cancel in the middle of a btrfs send, then run again immediately, the received subvolume doesn't get a Received UUID: field, and we won't mount it. Need to figure out a solution that will fix this.
 
 set -eE -o pipefail
 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
@@ -22,9 +23,9 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
 
 usage() {
-    echo "top of script file:"
-    sed -n '1,/^[# ]*end command line/{p;b};q' "$0"
-    exit $1
+  echo "top of script file:"
+  sed -n '1,/^[# ]*end command line/{p;b};q' "$0"
+  exit $1
 }
 
 script_dir=$(dirname $(readlink -f "$BASH_SOURCE"))
@@ -45,127 +46,119 @@ verbose=false
 
 default_args_file=/etc/btrbk-run.conf
 if [[ -s $default_args_file ]]; then
-    set -- $(< $default_args_file) "$@"
+  set -- $(< $default_args_file) "$@"
 fi
 
 temp=$(getopt -l help cl:m:nprt:vh "$@") || usage 1
 eval set -- "$temp"
 while true; do
-    case $1 in
-        # only creates the config file, does not run btrbk
-        -c) conf_only=true; shift ;;
-        -l) rate_limit=$2; shift 2 ;;
-        -m) IFS=, mountpoints=($2); unset IFS; shift 2 ;;
-        -n) dry_run=true; dry_run_arg=-n; shift ;;
-        -p) progress_arg="--progress"; shift ;;
-        # btrbk arg: Resume only. Skips snapshot creation.
-        -r) resume_arg=-r; shift ;;
-        # empty is valid for just doing local snapshot. we have default hosts
-        # we will populate
-        -t) IFS=, targets=($2); unset IFS; shift 2 ;;
-        -v) verbose=true; verbose_arg=-v; shift ;;
-        -h|--help) usage ;;
-        --) shift; break ;;
-        *) echo "$0: Internal error!" ; exit 1 ;;
-    esac
+  case $1 in
+    # only creates the config file, does not run btrbk
+    -c) conf_only=true; shift ;;
+    -l) rate_limit=$2; shift 2 ;;
+    -m) IFS=, mountpoints=($2); unset IFS; shift 2 ;;
+    -n) dry_run=true; dry_run_arg=-n; shift ;;
+    -p) progress_arg="--progress"; shift ;;
+    # btrbk arg: Resume only. Skips snapshot creation.
+    -r) resume_arg=-r; shift ;;
+    # empty is valid for just doing local snapshot. we have default hosts
+    # we will populate
+    -t) IFS=, targets=($2); unset IFS; shift 2 ;;
+    -v) verbose=true; verbose_arg=-v; shift ;;
+    -h|--help) usage ;;
+    --) shift; break ;;
+    *) echo "$0: Internal error!" ; exit 1 ;;
+  esac
 done
 
 if [[ -s $default_args_file ]]; then
-    echo "$0: warning: default btrbk-run options set in $default_args_file (sleeping 5 seconds):"
-    cat $default_args_file
-    sleep 5
+  echo "$0: warning: default btrbk-run options set in $default_args_file (sleeping 5 seconds):"
+  cat $default_args_file
+  sleep 5
 fi
 
 echo -e "$0: options: conf_only=$conf_only\ndry_run=$dry_run\nresume_arg=$resume_arg\nrate_limit=$rate_limit\nverbose=$verbose"
 
 # set default targets
 if [[ ! -v targets ]]; then
-    case $HOSTNAME in
-        x2|kw)
-            if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
-                targets=($HOME_DOMAIN)
-            fi
-            ;;
-        tp)
-            targets=(frodo)
-            if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
-                if timeout -s 9 10 ssh x2 :; then
-                    targets+=(x2)
-                fi
-            fi
-            ;;
-        frodo)
-            targets=()
-            ;;
-        *)
-            echo "$0: error: no default targets for this host, use -t"
-            exit 1
-            ;;
-    esac
+  case $HOSTNAME in
+    x2|kw)
+      if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
+        targets=($HOME_DOMAIN)
+      fi
+      ;;
+    tp)
+      targets=(frodo)
+      if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
+        if timeout -s 9 10 ssh x2 :; then
+          targets+=(x2)
+        fi
+      fi
+      ;;
+    frodo)
+      targets=()
+      ;;
+    *)
+      echo "$0: error: no default targets for this host, use -t"
+      exit 1
+      ;;
+  esac
 fi
 
 echo "targets: ${targets[*]}"
 
 
 
-if (( ${#mountpoints[@]} )); then
-    for mp in ${mountpoints[@]}; do
-        if [[ -e /nocow/btrfs-stale/$mp ]]; then
-            echo "$0: warning: $mp stale. Sleeping for 3 seconds in case you want to cancel."
-            sleep 3
-        fi
-    done
-else # set default mountpoints
-    case $HOSTNAME in
-        frodo)
-            prospective_mps=(/i)
-            ;;
-        *)
-            prospective_mps=(/a /q)
-            if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
-                prospective_mps+=(/o)
-            fi
-            ;;
-    esac
-    case ${targets[0]} in
-        kw|kww)
-            prospective_mps=(/a)
-            ;;
-    esac
-
-    for mp in ${prospective_mps[@]}; do # default mountpoints to sync
-        if [[ -e /nocow/btrfs-stale/$mp ]]; then
-            echo "$0: warning: $mp stale, not adding to default mountpoints"
-            continue
-        fi
-        if awk '{print $2}' /etc/fstab | grep -xF $mp &>/dev/null; then
-            mountpoints+=($mp)
-        fi
-    done
-fi
+# set default mountpoints
+case $HOSTNAME in
+  frodo)
+    prospective_mps=(/i)
+    ;;
+  *)
+    prospective_mps=(/a /q)
+    if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
+      prospective_mps+=(/o)
+    fi
+    ;;
+esac
+case ${targets[0]} in
+  kw|kww)
+    prospective_mps=(/a)
+    ;;
+esac
+
+for mp in ${prospective_mps[@]}; do # default mountpoints to sync
+  if [[ -e /nocow/btrfs-stale/$mp ]]; then
+    echo "$0: warning: $mp stale, not adding to default mountpoints"
+    continue
+  fi
+  if awk '{print $2}' /etc/fstab | grep -xF $mp &>/dev/null; then
+    mountpoints+=($mp)
+  fi
+done
 
 echo "mountpoints: ${mountpoints[*]}"
 
 ##### end command line parsing ########
 
 rsync-dirs() {
-    local host=$1
-    local path=$2
-    m rsync $dry_run_arg -ahi --relative --delete "$path" "root@$host:/"
+  local host=$1
+  local path=$2
+  m rsync $dry_run_arg -ahi --relative --delete "$path" "root@$host:/"
 }
 
 vol-conf() {
-    cat >>/etc/btrbk.conf <<EOF
+  cat >>/etc/btrbk.conf <<EOF
 volume $vol
 EOF
 }
 sub-conf() {
-    cat >>/etc/btrbk.conf <<EOF
+  cat >>/etc/btrbk.conf <<EOF
 subvolume $sub
 EOF
 }
 tg-conf() {
-    cat >>/etc/btrbk.conf <<EOF
+  cat >>/etc/btrbk.conf <<EOF
 target send-receive ssh://$tg$vol/btrbk
 EOF
 }
@@ -173,8 +166,13 @@ m() { printf "%s: %s\n" "${0##*/}" "$*";  "$@"; }
 
 
 if ! which btrbk &>/dev/null; then
-    echo "$0: error: no btrbk binary found"
+  echo "$0: error: no btrbk binary found"
+  exit 1
 fi
+# if our mountpoints are from stale snapshots,
+# it doesn't make sense to do a backup.
+check-subvol-stale ${mountpoints[@]} || exit 1
+
 
 cat >/etc/btrbk.conf <<EOF
 ssh_identity /root/.ssh/home
@@ -186,6 +184,9 @@ ssh_identity /root/.ssh/home
 # transaction info.
 transaction_syslog local7
 
+# 20%ish speedup[]
+stream_buffer 512m
+
 # so we only run one at a time
 lockfile                   /var/lock/btrbk.lock
 
@@ -212,35 +213,34 @@ rate_limit $rate_limit
 EOF
 
 
-# if our mountpoints are from stale snapshots,
-# it doesn't make sense to do a backup.
-check-subvol-stale ${mountpoints[@]} || exit 1
 
 for tg in ${targets[@]}; do
-    # for an initial run, btrbk requires the dir to exist
-    ssh root@$tg mkdir -p /mnt/root/btrbk
+  # for an initial run, btrbk requires the dir to exist.
+  # also use this opportunity to kill emacs, because it doesn't
+  # notice that the file has changed out from underneath it
+  ssh root@$tg mkdir -p /mnt/root/btrbk
 done
 
 
 for m in ${mountpoints[@]}; do
-    # for /i, some special cases. there is just one static target and direction.
-    if [[ $m == /i ]]; then
-        vol=/mnt/iroot
-        vol-conf
-        sub=i
-        sub-conf
-        tg=frodo
-        vol=/mnt/root
-        tg-conf
-    else
-        vol=/mnt/root
-        vol-conf
-        sub=${m##*/}
-        sub-conf
-        for tg in ${targets[@]}; do
-            tg-conf
-        done
-    fi
+  # for /i, some special cases. there is just one static target and direction.
+  if [[ $m == /i ]]; then
+    vol=/mnt/iroot
+    vol-conf
+    sub=i
+    sub-conf
+    tg=frodo
+    vol=/mnt/root
+    tg-conf
+  else
+    vol=/mnt/root
+    vol-conf
+    sub=${m##*/}
+    sub-conf
+    for tg in ${targets[@]}; do
+      tg-conf
+    done
+  fi
 done
 
 
@@ -249,35 +249,35 @@ done
 
 
 if $conf_only; then
-    exit
+  exit
 fi
 
 if $dry_run; then
-    m btrbk -v -n $resume_arg run
+  m btrbk -v -n $resume_arg run
 else
-    # -q and just using the syslog option seemed nice,
-    # but it doesn't show when a send has a parent and when it doesn't.
-    m btrbk $verbose_arg $progress_arg $resume_arg run
+  # -q and just using the syslog option seemed nice,
+  # but it doesn't show when a send has a parent and when it doesn't.
+  m btrbk $verbose_arg $progress_arg $resume_arg run
 fi
 
 # if we have it, sync to systems which don't
 if mountpoint $rsync_mountpoint >/dev/null; then
-    for tg in ${targets[@]}; do
-        case $tg in
-            tp|li|lk)
-                for x in /p/c/machine_specific/*.hosts; do
-                    if grep -qxF $tg $x; then
-                        dir=${x%.hosts}
-                        rsync-dirs $tg $dir
-                    fi
-                done
-                ;;
-        esac
-    done
+  for tg in ${targets[@]}; do
+    case $tg in
+      tp|li|lk)
+        for x in /p/c/machine_specific/*.hosts; do
+          if grep -qxF $tg $x; then
+            dir=${x%.hosts}
+            rsync-dirs $tg $dir
+          fi
+        done
+        ;;
+    esac
+  done
 fi
 
 if ! $dry_run; then
-    m $script_dir/mount-latest-remote ${targets[@]}
+  m $script_dir/mount-latest-remote ${targets[@]}
 fi