X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=btrbk-run;h=a1c6963a926b445454ca1d27634a56737e2d34da;hb=0310db0c0589445a132e77f0b7a8fbb5e1ae3082;hp=4642a708c1328198fb1cad6a66c5f75a8349dda2;hpb=f3e6a97425746ed185c28dcc03acf7e67a6af560;p=distro-setup diff --git a/btrbk-run b/btrbk-run index 4642a70..a1c6963 100755 --- a/btrbk-run +++ b/btrbk-run @@ -13,10 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. + +# todo: remove old leaf subvols, like keep up to 1 month or something. + set -eE -o pipefail 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" @@ -27,38 +31,120 @@ script_dir=$(dirname $(readlink -f "$BASH_SOURCE")) # note q is owned by root:1000 # note p/m is owned 1000:1000 and chmod 700 -mountpoints=(/a) -private_mountpoints=(/q) + + +mountpoints=() + rsync_mountpoint=/q conf_only=false dry_run=false # mostly for testing resume_arg= -do_i=true -do_o=true +rate_limit=no +verbose=false + +default_args_file=/etc/btrbk-run.conf +if [[ -s $default_args_file ]]; then + set -- $(< $default_args_file) "$@" +fi -temp=$(getopt -l help hcinoprt: "$@") || usage 1 +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 ;; - -i) do_i=false; shift ;; + -l) rate_limit=$2; shift 2 ;; + -m) IFS=, mountpoints=($2); unset IFS; shift 2 ;; -n) dry_run=true; dry_run_arg=-n; shift ;; - -o) do_o=false; 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 $do_o; then - private_mountpoints+=(/o) +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 fi -read primary <<<"$@" # not yet used + +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 +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 + +echo "mountpoints: ${mountpoints[*]}" ##### end command line parsing ######## @@ -90,8 +176,8 @@ if ! which btrbk &>/dev/null; then echo "$0: error: no btrbk binary found" fi -cat >/etc/btrbk.conf <<'EOF' -ssh_identity /root/.ssh/id_rsa +cat >/etc/btrbk.conf </dev/null; then - mountpoints+=($mp) - fi -done # if our mountpoints are from stale snapshots, # it doesn't make sense to do a backup. check-subvol-stale ${mountpoints[@]} || exit 1 -if [[ ! $targets ]]; then - case $HOSTNAME in - tp|x2) - if ! timeout -s 9 10 ssh frodo :; then - targets=($HOME_DOMAIN) - fi - ;; - treetowl) - targets=(frodo) - if timeout -s 9 10 ssh x2 :; then - targets+=(x2) - fi - ;; - *) - targets=(frodo) - ;; - esac - echo "targets: ${targets[*]}" -fi - - -# for i, we just do a 1 way sync from master to backup, -# and manually manage any changes to that. -i_possible=false for tg in ${targets[@]}; do # for an initial run, btrbk requires the dir to exist ssh root@$tg mkdir -p /mnt/root/btrbk - if [[ $tg == frodo && $HOSTNAME == treetowl ]]; then - i_possible=true - fi done -if ! $i_possible; then - do_i=false -fi -vol=/mnt/root -vol-conf for m in ${mountpoints[@]}; do - sub=${m##*/} - sub-conf - for tg in ${targets[@]}; 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 - done + else + vol=/mnt/root + vol-conf + sub=${m##*/} + sub-conf + for tg in ${targets[@]}; do + tg-conf + done + fi done -if $do_i; then - vol=/mnt/iroot - vol-conf - sub=i - sub-conf - tg=frodo - vol=/mnt/root - tg-conf -fi - - # todo: umount first to ensure we don't have any errors # todo: do some kill fuser stuff to make umount more reliable -# todo: run this on a systemd timer on $primary, once per hour, -# and if primary is, change that timer over to primary, and make -# sure we mount the latest - if $conf_only; then @@ -204,11 +253,11 @@ if $conf_only; then fi if $dry_run; then - m btrbk -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 $progress_arg $resume_arg run + m btrbk $verbose_arg $progress_arg $resume_arg run fi # if we have it, sync to systems which don't