bug fix pull & simplify. avoid 2d array with spaces + lines
authorIan Kelling <ian@iankelling.org>
Thu, 9 Oct 2025 01:21:25 +0000 (21:21 -0400)
committerIan Kelling <ian@iankelling.org>
Thu, 9 Oct 2025 01:21:25 +0000 (21:21 -0400)
filesystem/usr/local/bin/btrbk-run

index 7f5ee3f9e5248bd7d026ce78b5dacf0c52aeb35b..f7486e3c4424191e7c2274695590d430d43a7d86 100755 (executable)
 # field, and we won't mount it. Need to figure out a solution that will
 # fix this.
 
+# todo: I took out qr because I moved it to a different disk at home,
+# and dont feel like updating this script to deal with that. Make sure
+# it is getting backed up, maybe having just a backup of qr on my
+# desktop is good enough.
 
 [[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
 
@@ -171,6 +175,8 @@ EOF
 
 
 write-config() {
+  local q_mp=false
+  local -a tmp_mps
 
   cat >/etc/btrbk$conf_suf.conf <<EOF
 ssh_identity /q/root/h
@@ -219,14 +225,18 @@ incremental strict
 EOF
   fi
 
-  # make /q be last
+  # make /q be last.
   mp_count=${#mountpoints[@]}
   for (( i=0; i < mp_count - 1 ; i++ )); do
     if [[ ${mountpoints[i]} == /q ]]; then
-      unset "mountpoints[i]"
-      mountpoints+=(/q)
+      q_mp=true
+    else
+      tmp_mps+=(${mountpoints[i]})
     fi
   done
+  if $q_mp; then
+    mountpoints=( "${tmp_mps[@]}" /q )
+  fi
 
 
 
@@ -248,7 +258,7 @@ EOF
 
     if [[ $source ]]; then
       tmp_a=($vol/btrbk/$sub.*)
-      tg_snaps+=("${tmp_a[*]}")
+      tg_snaps+=("${tmp_a[@]}")
       cat >>/etc/btrbk$conf_suf.conf <<EOF
 volume ssh://$bbksource$vol
 subvolume $sub
@@ -287,6 +297,7 @@ EOF
     fi
   done
 
+
   if $conf_only; then
     mexit 0
   fi
@@ -295,27 +306,53 @@ EOF
 
 
 get-orphan-tg-snaps() {
-  orphan_tg_snaps=()
-  for (( i=0; i < ${#mountpoints[@]}; i++ )); do
-    orphan_start_count=${#orphan_tg_snaps[@]}
-    tg_snap_count=0
-    for tg_snap in ${tg_snaps[$i]}; do
-      tg_snap_count=$(( tg_snap_count + 1 ))
-      if [[ ! ${source_snaps[$tg_snap]} ]]; then
-        orphan_tg_snaps+=("$tg_snap")
+  local mp_to_snap_regex snap
+  local -a mp_orphan_tg_snaps mp_tg_snaps
+
+  ## sanity checking
+  for (( i=0; i < ${#tg_snaps[@]}; i++ )); do
+    if [[ ! ${tg_snaps[$i]} =~ $good_path_regex ]]; then
+      die "bad var: tg_snaps[$i] '${tg_snaps[$i]}'"
+    fi
+  done
+  for snap in "${!source_snaps[@]}"; do
+    if [[ ! $snap =~ $good_path_regex ]]; then
+      die "bad source snap: '$snap'"
+    fi
+  done
+
+
+  # note: we do each mountpoint separately just so we can better sanity
+  # check that we aren't incorrectly classifying all target snaps as
+  # orphans.
+  for mp in "${mountpoints[@]}"; do
+    mp_orphan_tg_snaps=()
+    mp_tg_snaps=()
+    mp_to_snap_regex="$mp"'\.[0-9]{8}T[0-9]{6}-[0-9]{4}$'
+    for tg_snap in "${tg_snaps[@]}"; do
+      if [[ $tg_snap =~ $mp_to_snap_regex ]]; then
+        mp_tg_snaps+=("$tg_snap")
       fi
     done
-    orphan_mp_count=$(( ${#orphan_tg_snaps[@]} - orphan_start_count ))
-    # sanity checking
-    tmp=$(( tg_snap_count  > 1 && tg_snap_count == orphan_mp_count ))
-    if (( tmp )) ; then
-      if [[ $source ]]; then
-        tg_host=$HOSTNAME
-      else
-        tg_host=$tg
+    for mp_tg_snap in "${mp_tg_snaps[@]}"; do
+      if [[ ! ${source_snaps[$mp_tg_snap]} ]]; then
+        orphan_tg_snaps+=("$tg_snap")
+        mp_orphan_tg_snaps+=("$tg_snap")
       fi
-      die "something went wrong checking orphans on $tg_host: for mountpoint ${mountpoints[$i]}, $orphan_mp_count. tg_snaps:${tg_snaps[*]}, source_snaps: ${!source_snaps[*]}"
-    fi
+
+      ## sanity checking
+      tmp=$(( ${#mp_tg_snaps[@]} >= 1 && ${#mp_orphan_tg_snaps[@]} == ${#mp_tg_snaps[@]} ))
+      if (( tmp )) ; then
+        if [[ $source ]]; then
+          tg_host=$HOSTNAME
+        else
+          tg_host=$tg
+        fi
+        die "something went wrong checking orphans on $tg_host: for mountpoint: $mp, mp_tg_snaps: ${mp_tg_snaps[*]},
+source_snaps: ${!source_snaps[*]}"
+      fi
+    done
+
   done
 }
 
@@ -350,10 +387,10 @@ del-orphan-snaps() {
     fi
   else # we have targets
     for tg in ${targets[@]}; do
-      tmp_str=$(ssh root@$tg "shopt -s nullglob; echo $snap_list_glob")
-      mapfile -t tg_snaps <<<"$tmp_str"
+      tmpstr=$(ssh root@$tg "shopt -s nullglob; echo $snap_list_glob")
+      IFS=" " read -r -a tg_snaps <<<"$tmpstr"
       get-orphan-tg-snaps
-      tmp=$(( ${#orphan_tg_snaps[*]} >= 1 ))
+      tmp=$(( ${#orphan_tg_snaps[@]} >= 1 ))
       if (( tmp )); then
         d ssh root@$tg "btrfs sub del ${orphan_tg_snaps[*]}"
       fi
@@ -379,6 +416,7 @@ fi
 
 # note q is owned by root:1000
 
+good_path_regex='^[-a-zA-Z0-9/._]+$'
 snap_path_regex='[a-z]/btrbk/[a-z]+\.[0-9]{8}T[0-9]{6}-[0-9]{4}$'
 declare -A source_snaps
 mountpoints=()
@@ -392,7 +430,7 @@ dry_run=false # mostly for testing
 rate_limit=no
 # -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.
-verbose=true; verbose_arg="-l trace"
+verbose=false; verbose_arg=
 force=false
 if [[ $PPID == 1 || $INVOCATION_ID || $SYSTEMD_EXEC_PID ]]; then
   # running as a service. we cant show progress in this case,
@@ -441,7 +479,7 @@ while true; do
     -3) conf_suf=3 ;;
     -a)
       # all moiuntpoints
-      mountpoints=(/a /o /qr /q)
+      mountpoints=(/a /o /q)
       ;;
     # only creates the config file, does not run btrbk
     -c) conf_only=true ;;
@@ -648,24 +686,24 @@ else
             prospective_mps+=(/o)
           fi
           if [[ $source_host == "$HOST2" ]]; then
-            prospective_mps+=(/a /qr /q)
+            prospective_mps+=(/a /q)
           fi
         else
           if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
             prospective_mps+=(/o)
           fi
           if [[ $HOSTNAME == "$HOST2" ]]; then
-            prospective_mps+=(/a /qr /q)
+            prospective_mps+=(/a  /q)
           fi
           if $kd_spread; then
-            prospective_mps=(/a /o /qr /q)
+            prospective_mps=(/a /o  /q)
           fi
         fi
         # If the above conditions didnt add any mountpoints, and host
         # status is empty, then add all mointpoints. This is a case of
         # doing something like kd_spread manually.
         if [[ ! ${prospective_mps[0]} && $source_host != "$HOST2" && $source_host != "$MAIL_HOST" && $HOSTNAME != "$MAIL_HOST" && $HOSTNAME != "$HOST2"  ]]; then
-          prospective_mps=(/a /o /qr /q)
+          prospective_mps=(/a /o  /q)
         fi
 
         # note: put q last just in case its specific retention options were to