various fixes and improvements
authorIan Kelling <ian@iankelling.org>
Sat, 1 Mar 2025 18:21:52 +0000 (13:21 -0500)
committerIan Kelling <ian@iankelling.org>
Sat, 1 Mar 2025 18:22:08 +0000 (13:22 -0500)
prevent erasing backups when no source backups found

13 files changed:
beet-data
brc2
brc3
filesystem/etc/systemd/system/znc.service.d/override.conf
filesystem/usr/local/bin/btrbk-run
filesystem/usr/local/bin/switch-mail-host
fsf-script-lib
g
machine_specific/frodo/filesystem/etc/btrbk/rust.conf
machine_specific/li/filesystem/etc/openvpn/client-config-hole/librestation03 [new file with mode: 0644]
machine_specific/librestation03/filesystem/etc/systemd/system/openvpn-client-tr@.service [new file with mode: 0644]
mail-setup
myx

index 52c1256fc06bcdd5f075212b996576e32d6d9beb..7e9dc732a86856f89c14a6c3595a5570b4d07df3 100644 (file)
--- a/beet-data
+++ b/beet-data
@@ -133,7 +133,7 @@ beetapl() { # beet add playlist
 
 # this function is just so we can have some local vars
 # and not mess with the global var namespace.
-_beet-gen-global-vars() {
+beet-gen-global-vars() {
 
   local first g t r
 
diff --git a/brc2 b/brc2
index c55eca9627d6602767add013f36e8eff8975d613..02b00d030d44e2761005e4cc56dbaa01a3a7dc16 100644 (file)
--- a/brc2
+++ b/brc2
@@ -686,10 +686,10 @@ beets-gen-playlists() {
 EOF
   done
 }
+source /a/bin/ds/beet-data
 
 # beet playlist. use beetag with a playlist name
 bpl() {
-  source /a/bin/ds/beet-data
   local playlist playlist_regex
   case $1 in
     -h|--help)
@@ -2631,7 +2631,7 @@ hiup() {
   # incomplete local vars list
   local usb ip host mac opts
   local -A vpn_ips host_ips host_macs portfw_ips nonvpn_ips all_ips root_hosts_a
-  local -a root_hosts nonroot_hosts
+  local -a root_hosts nonroot_hosts work_hosts
 
   # the hosts with no mac
   root_hosts=( bk je li b8.nz )
@@ -2672,7 +2672,9 @@ hiup() {
     else
       nonvpn_ips[$host]=$ip
     fi
-    if $root; then
+    if [[ $host == librestation03 ]]; then
+      work_hosts+=($host ${host}wg)
+    elif $root; then
       # note: the reason we have b8.nz suffix here but not for non_root
       # hosts is that it is for the User part, the IdentityFile part is
       # redundant to *.b8.nz. Also note ${host}i, we only setup those for vpn hosts, but there is no harm in overspecifying here.
@@ -2691,6 +2693,10 @@ hiup() {
 
   {
     cat <<EOF
+Host ${work_hosts[@]}
+User root
+IdentityFile ~/.ssh/work
+
 Host ${nonroot_hosts[@]}
 User iank
 IdentityFile ~/.ssh/home
@@ -2710,7 +2716,7 @@ EOF
     # convenience of one auth key entry
     for host in ${!all_ips[@]}; do
       cat <<EOF
-Host $host ${host}i $host.b8.nz ${host}i.b8.nz
+Host $host ${host}i ${host}vp ${host}wg $host.b8.nz ${host}i.b8.nz ${host}vp.b8.nz ${host}wg.b8.nz
 HostKeyAlias $host.b8.nz
 EOF
     done
@@ -2981,7 +2987,7 @@ EOF
   rootsshsync
 }
 
-# usage host ipsuf [extrahost]
+# usage: called from hiup which sets up a hash ${vpn_hosts[@]} which this function uses. Args: host ipsuf [extrahost]
 #
 # This doesn't do all the work, hiup is also needed, as it sets up
 # config on li.
@@ -3476,11 +3482,14 @@ myprof() {
   for (( ; i < logcount; i++ )); do
     log_base=${logs[$i]}
     day_logs=()
-    if [[ -e office_at_conference.fsf.org/$log_base ]]; then
+    if [[ -s office_at_conference.fsf.org/$log_base ]]; then
       day_logs+=(office_at_conference.fsf.org/$log_base)
     fi
-    if [[ -e sys_at_conference.fsf.org/$log_base ]]; then
-      day_logs+=(office_at_conference.fsf.org/$log_base)
+    if [[ -s sys_at_conference.fsf.org/$log_base ]]; then
+      day_logs+=(sys_at_conference.fsf.org/$log_base)
+    fi
+    if (( ${#day_logs[@]} == 0 )); then
+      continue
     fi
     d=$(date -d "$(head -n1 ${day_logs[0]} |awk '{print $1}')" +%s)
     if (( d < min_date )); then
@@ -5249,6 +5258,13 @@ linediff() {
   meld <(printf "%s\n" "$l1") <(printf "%s\n" "$l2") &
 }
 
+# list count of files in directories
+wc-l-dirs() {
+  for f in "$@"; do
+    e $(ls -1Uq $f| wc -l) $f
+  done | sort -n
+}
+
 export BASEFILE_DIR=/a/bin/fai-basefiles
 
 #export ANDROID_HOME=/a/opt/android-home
diff --git a/brc3 b/brc3
index 82ea3db0e100af4235d1ef43d0375dee1149278e..d1386b32e3799df89d7de105bad80b104ee584c7 100644 (file)
--- a/brc3
+++ b/brc3
@@ -4,6 +4,11 @@
 # and I have no desire to always load them into my shell.
 
 
+#  when running startx on my 4k tiny monitor
+startx-dpi() {
+  startx -- -dpi 120
+}
+
 ## todo: make this get all the package lists
 # if [[ ! -e main ]]; then
 #   wget http://archive.ubuntu.com/ubuntu/dists/noble/{main,universe}/binary-amd64/Packages.gz
@@ -124,4 +129,4 @@ schroot-cleanup() {
 # usage: pass encoded string on stdin
 url-decode() {
   python3 -c "import sys; from urllib.parse import unquote; print(unquote(sys.stdin.read()));"
-  }
+}
index a69bdc3ab085b3275634d7f4806fee8aded9e079..d32f55e923ffc1754d34407632eb79bc1494979a 100644 (file)
@@ -1,2 +1,5 @@
 [Service]
 ExecStartPre=/a/c/znc-start-delay
+Restart=always
+RestartSec=30
+TimeoutStartSec=300
index 9af45e293787de364c2afcf8eb48e43eee2b3e54..3bad9c4f1bad7afd0fed9c2d06827c0004c2ff1b 100755 (executable)
@@ -267,7 +267,14 @@ EOF
 target send-receive $vol/btrbk
 EOF
     else # we have targets
-      for snap in "$vol/btrbk/$sub."*; do
+      tmp_snaps=( "$vol/btrbk/$sub."* )
+      if ! $force && (( ${#tmp_snaps[@]} == 0 )); then
+        die "found no snaps from $vol/btrbk/$sub.* . If expected, rerun with -f ."
+      fi
+      for snap in "${tmp_snaps[@]}"; do
+        if [[ ! $snap =~ $snap_path_regex ]]; then
+          die "got invalid source snap from $vol/btrbk/$sub.*: $snap"
+        fi
         source_snaps[$snap]=t
       done
 
@@ -321,6 +328,7 @@ get-orphan-tg-snaps() {
   done
 }
 
+
 # Note, this depends on write-config being called first.
 #
 # Delete any subvols on the receiving host that don't exist on the
@@ -332,13 +340,17 @@ get-orphan-tg-snaps() {
 del-orphan-snaps() {
   if [[ $source ]]; then
     tmpstr=$(ssh root@$source "shopt -s nullglob; echo $snap_list_glob")
-    if [[ ! $tmpstr ]]; then
-      die "got empty string when listing source subvolumes"
-    fi
     IFS=" " read -r -a source_snap_list <<<"$tmpstr"
+    if ! $force && (( ${#source_snap_list[@]} == 0 )); then
+      die "found no snaps from glob:$snap_list_glob on host:$source . If expected, rerun with -f ."
+    fi
     for snap in "${source_snap_list[@]}"; do
+      if [[ ! $snap =~ $snap_path_regex ]]; then
+        die "invalid source snap:$snap from glob:$snap_list_glob on host:$source ."
+      fi
       source_snaps[$snap]=t
     done
+
     # tg_snaps was set earlier
     get-orphan-tg-snaps
     tmp=$(( ${#orphan_tg_snaps[*]} >= 1 ))
@@ -376,6 +388,7 @@ fi
 
 # note q is owned by root:1000
 
+snap_path_regex='[a-z]/btrbk/[a-z]+\.[0-9]{8}T[0-9]{6}-[0-9]{4}$'
 declare -A source_snaps
 mountpoints=()
 
index 7165acf2ff808028ada3bb54160c46a37b9cb851..a0079b4d554a81c41e12c7719e20381eb1f632d1 100755 (executable)
@@ -304,11 +304,11 @@ for dir in m o; do
 done
 EOF
     fi
-  } | $new_shell bash -s
+  } | $new_shell bash -se
 fi
 
 if ! $mail_only; then
-  cat /usr/local/bin/unsaved-buffers - <<'EOF' |  $old_shell bash -s
+  cat /usr/local/bin/unsaved-buffers - <<'EOF' |  $old_shell bash -se
 
 # Try to prevent emacs from saving stale data it has in memory to disk. eg: files, recentf list, etc.
 # But if emacs ignores the signal, let it live.
index 8f50a96c177f740a22605688f25a7a4b9cce4851..ddcfce96d55acc27744836c9447e0f315b87c3ba 100644 (file)
@@ -39,6 +39,38 @@ elif [[ $- != *i* ]]; then
 fi
 set +e
 
+# Use the following to validate int inputs like so:
+# if [[ ! $some_var =~ $int_regex ]]; then
+#   echo "error: some_var=$some_var"
+#   exit 1
+# fi
+
+# shellcheck disable=SC2034
+int_regex='^-?[0-9]+$'
+# unsigned int, no negative.
+# shellcheck disable=SC2034
+uint_regex='^[0-9]+$'
+
+
+rm-maybe() {
+  if (( $# )); then
+    rm -f "$@"
+  fi
+}
+
+# ln -st + maybe + mkdir
+ln-st() {
+  local dir="$1"
+  shift
+  if (( $# == 0 )); then
+    return 0
+  fi
+  if [[ ! -d "$dir" ]]; then
+    mkdir -p "$dir"
+  fi
+  ln -st "$dir" "$@"
+}
+
 
 # low pri todo: compare this to a screen or tmux log.
 slog() {
@@ -70,6 +102,7 @@ slog() {
 # echo COMMAND then run it.
 m() { printf "+ %s\n" "$*" >&2;  "$@"; }
 
+
 # mb, maybe. echo args if they fail.
 mb() {
   local ret=0
@@ -82,19 +115,60 @@ mb() {
 
 # usage: e [MESSAGE...]
 #
-# echo MESSAGE.
-if [[ $- == *i*  ]]; then
-  # prefix doesn't make sense in interactive shell
-  e() { printf "%s\n" "$*"; }
-else
-  e() {
-    if [[ $debug_interact ]]; then
-      printf "%s\n" "$*"
+# echo MESSAGE, but use printf so it is safe from options.
+e() { printf "%s\n" "$*"; }
+
+# usage: ml COMMAND...
+#
+# Write successful command to log.
+#
+# Set $log_path, else it is the script name + log,
+# else ~/log/date.log.
+#
+# If $dry_run == true, then just print the command.
+#
+# if [[ $debug == true || $verbose == true ]], then also print the command.
+ml() {
+  local timestamp ret=0
+  # shellcheck disable=SC2154 # expected for caller to set dry_run if they want it.
+  if [[ $dry_run == true ]]; then
+    printf "%s\n" "$*"
+    return 0
+  fi
+  "$@" || ret=$?
+  if (( ret )); then
+    printf "error: exit code $ret from: %s\n" "$*" >&2
+    return $ret
+  else
+    if [[ ! $log_path ]]; then
+      local log_path
+      # shellcheck disable=SC2124 # false positive
+      log_path="${BASH_SOURCE[@]: -1}.log"
+      if [[ ! $log_path ]]; then
+        log_path=$HOME/log/$(date "+%F")
+      fi
+    fi
+    timestamp=$(date "+%F %T")
+    # shellcheck disable=SC2154 # expected for caller to set $verbose if they want it.
+    if [[ $debug == true || $verbose == true ]]; then
+      printf "%s %s\n" "$timestamp" "$*" |tee -a "$log_path"
     else
-      printf "${0##*/}: %s\n" "$*"
+      printf "%s %s\n" "$timestamp" "$*" >>"$log_path"
     fi
-  }
-fi
+  fi
+}
+
+# usage: dr COMMAND...
+#
+# Run COMMAND if not $dry_run == true, in that case print it.
+dr() {
+  if [[ $dry_run == true ]]; then
+    printf "%s\n" "$*"
+  else
+    "$@"
+  fi
+}
+
 
 # usage: err [ERROR_MESSAGE...]
 #
@@ -115,9 +189,9 @@ err() { echo "$(date "+%F %T") ${FUNCNAME[1]}: $*" >&2; }
 #
 # - Related function h() to prompt before executing printed command.
 #
-# Be default, no printing of commands inside functions. To enable, either
+# Printing of uninteresting commands can be limited:
 #
-# 1: set debug_max_stack_depth to >= 1. Default = 0.
+# 1: Do not print command when stack depth is >= debug_max_stack_depth.
 #
 # 2: Allow printing in specific functions with setx-func (see its doc below).
 #
@@ -152,7 +226,7 @@ _debug-setx-func() {
     funcname_count_max=$(( debug_max_stack_depth + 1 ))
   else
     # within 0 func level, FUNCNAME has 2 in here, eg debug-setx-func main.
-    funcname_count_max=2
+    funcname_count_max=99999
   fi
 
   if [[ $BASH_SUBSHELL != [01] ]]; then
@@ -344,3 +418,80 @@ setx-func() {
 }
 
 ### end debug-setx related functions ###
+
+## begin debug-setx background / development notes
+#
+# I often end up writing little 5-10 line scripts. To log what they are doing,
+# I was annoyed with the available options. #1 There is set -x, which usually ends up
+# being > 50% useless lines, very anoying. #2
+# m() { printf "%s\n" "$*";
+#"$@"; } that annoyingly conflicts with command
+# redirected output, and I constantly forget to add it.
+#
+# Better option: debug trap, where we can print $BASH_COMMAND. The main
+# annoying thing about this is that $BASH_COMMAND doesn't have expanded
+# variables.
+#
+# options to expand variables in a $BASH_COMMAND:
+#
+# 1. get bash to do readline's shell-expand-line. I know a hacky way
+# with read, but it wasn't reliable when I tried it in a
+# prompt_command. I could probably create a c program that uses readline
+# to do it pretty easily
+#
+# 2. Use the prompt expansion features @P, but first escape the special
+# prompt characters if there are any. This was the option I went
+# with. It has a small flaw that I realized without calling a regex
+# substitution program, my escaping is not perfect: I temporarily insert
+# a long random string to identify "\\", but it is possible this string
+# could exist in the command and then I would improperly replace
+# it. However, my use case is simply viewing commands I intend to run
+# and I don't see any reason I would intend to run a command with that
+# or that even if I did, it would cause any serious problem to have it
+# be incorrectly displayed.
+#
+# NOTE: One imperfection with both of these, is that we don't want to
+# expand $() or ``, so I look for those chars and then avoid doing it. I
+# think the only way to avoid this would be to modify bash itself in
+# order to do shell-expand-line and then use the result, just as if you
+# pressed the key for it.
+#
+# \\ -> \\\\ : creates problem matching eg: \e
+#
+# alternate:
+#
+# \134 -> RANDOM_LONG_STRING
+#
+# \\ -> \134\134 : creates problem matching \134, we need to match \134!(\134), solved by the RANDOM_LONG_STRING
+#
+# \a -> \134a
+#
+# \D{*} and \123 -> \\&
+#
+# RANDOM_LONG_STRING -> \\134
+#
+# alternate, best:
+#
+# \\ -> RANDOM_LONG_STRING
+#
+# \a -> \\a
+#
+# \D{*} and \123 -> \\&
+#
+# RANDOM_LONG_STRING -> \\\\
+#
+# # incrementally built up test cases, where the output is expected to be the same as the initial _d
+#
+# _d='ok\\\\jyes'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
+#
+# _d='ok\D{z_ds}yes'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
+#
+# _d='ok\144ye\134s'; _d="${_d//'\\'/SUBfopguensOfRifejmuSUB}" _d="${_d//\\[adehHjlnrstT@AuvVwW\!\#\$[\]]/\\&}" _d="${_d//\\D\{*\}/\\&}" _d="${_d//\\[012][0-9][0-9]/\\&}" _d="${_d//\\3[0-6][0-9]/\\&}" _d="${_d//\\37[0-7]/\\&}" _d="${_d//SUBfopguensOfRifejmuSUB/'\\\\'}"; e "$_d  +  ${_d@P}"
+#
+#
+# random interesting script:
+# x=4
+# echo "\$x ${BASH_COMMAND@P}"
+# Warning: Program '/bin/bash' crashed.
+#
+## end debug-setx background / development notes
diff --git a/g b/g
index a88df4b0dcb26861e6c543ede1c69ab392b80702..aaa9ac667142dd4b71d4ed09b7379132874d2e9d 100755 (executable)
--- a/g
+++ b/g
@@ -75,4 +75,5 @@ g() {
   fi
 }
 
+#echo "$*" >>/tmp/g.log
 g "$@"
index 28032b16460b39a886ecd2ddb8cc6ddb9c34d9af..9c47db02780b714b4d68073c82c99553c24e57f2 100644 (file)
@@ -7,18 +7,13 @@ timestamp_format long-iso
 snapshot_create onchange
 
 snapshot_preserve 18h 14d 8w 12m
-snapshot_preserve_min 2h
+snapshot_preserve_min 2d
 snapshot_dir btrbk
 
 target_preserve 18h 14d 8w 12m
-target_preserve_min 2h
+target_preserve_min 2d
 
 rate_limit no
-volume /mnt/r7
+volume /mnt/rbackup
 subvolume d
-target send-receive /mnt/rust1/btrbk
-target send-receive /mnt/rust2/btrbk
-
-subvolume ar
-target send-receive /mnt/rust1/btrbk
-target send-receive /mnt/rust2/btrbk
+subvolume roverflow
diff --git a/machine_specific/li/filesystem/etc/openvpn/client-config-hole/librestation03 b/machine_specific/li/filesystem/etc/openvpn/client-config-hole/librestation03
new file mode 100644 (file)
index 0000000..bed73fe
--- /dev/null
@@ -0,0 +1 @@
+ifconfig-push 10.5.5.99 255.255.255.0
diff --git a/machine_specific/librestation03/filesystem/etc/systemd/system/openvpn-client-tr@.service b/machine_specific/librestation03/filesystem/etc/systemd/system/openvpn-client-tr@.service
new file mode 100644 (file)
index 0000000..90e839b
--- /dev/null
@@ -0,0 +1,36 @@
+[Unit]
+Description=OpenVPN tunnel for %I
+After=syslog.target network-online.target
+Wants=network-online.target
+Documentation=man:openvpn(8)
+Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
+Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
+Requires=iptables.service
+
+[Service]
+Type=notify
+RuntimeDirectory=openvpn-client
+RuntimeDirectoryMode=0710
+WorkingDirectory=/etc/openvpn/client
+ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config /etc/openvpn/client/%i.conf
+# todo, try reenabling this from the default openvpn,
+# it was disabled so we could do bind mounts as a command,
+# but now systemd handles it
+#CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE
+LimitNPROC=10
+# DeviceAllow=/dev/null rw
+# DeviceAllow=/dev/net/tun rw
+
+# we use .1 to make this be on a different network than kd, so that we can
+# talk to transmission on kd from remote host, and still use this
+# vpn.
+ExecStartPre=/usr/bin/flock -w 20 /tmp/newns.flock /a/bin/newns/newns -n 10.174.99 start %i
+ExecStartPre=/sbin/iptables-restore /a/bin/distro-setup/transmission-firewall/netns.rules
+# allow wireguard network to connect
+ExecStartPre=/usr/sbin/ip r add 10.8.0.0/24 via 10.174.99.1 dev veth1-client
+ExecStopPost=/usr/bin/flock -w 20 /tmp/newns.flock /a/bin/newns/newns stop %i
+PrivateNetwork=true
+BindReadOnlyPaths=/etc/tr-resolv:/run/systemd/resolve:norbind /etc/basic-nsswitch:/etc/resolved-nsswitch:norbind
+
+[Install]
+WantedBy=multi-user.target
index 0d71591771c416db0f30a14591346733a1fe30d9..6d48cb4cfcab47f048e3a9e025e5f572292770bf 100755 (executable)
 #
 #&! testignore|jtuttle|eximbackup|/usr/sbin/exim4 -bpu
 
+# todo: this should have been rejected at smtp-time. the <FF> is a translation of �
+# 2025-02-28 23:41:40 [3939978] 1toEfR-0000000GWy2-4A1N <= <FF>Amazon.meguminozaki@tischlermeister-luempert.de H=(localhost) [183.167.149.235] P=esmtp S=9416 id=1461312104.1131284.1740804083757@localhost T="\343\200\214\351\207\215\350\246\201\343\201\252\343\201\212\347\237\245\343\202\211\343\201\233\357\274\232\343\202\242\343\202\253\343\202\246\343\203\263\343\203\210\345\206\215\350\252\215\350\250\274\343\201\256\343\201\212\351\241\230\343\201\204\343\200\215" from <<FF>Amazon.meguminozaki@tischlermeister-luempert.de> for ian@iankelling.org
+# 2025-02-28 23:41:41 [3940022] 1toEfR-0000000GWy2-4A1N ** ian@iankelling.org F=<<FF>Amazon.meguminozaki@tischlermeister-luempert.de> P=<<FF>Amazon.meguminozaki@tischlermeister-luempert.de> R=local_user T=dovecot_lmtp: LMTP error after MAIL FROM:<\377Amazon.meguminozaki@tischlermeister-luempert.de>: 500 5.5.2 Invalid command syntax DT=0s
+# There was nothing useful in /var/log/mail.log.
+
 # todo: this message seems to get dropped on the floor, it was due to a missing 2nd colon in
 #  condition = ${if def:h_fdate:}
 # Figure out how to avoid this message being discarded.
diff --git a/myx b/myx
index 25207953af2a04281b8e611a7eaf618fcefafca8..18a81dff1cc383f202d868663a27d0447e5dfe61 100755 (executable)
--- a/myx
+++ b/myx
@@ -303,13 +303,21 @@ done
 
 {
   cat /a/bin/ds/i3-sway/bar.conf
-  if [[ $secondary_out ]]; then
-    echo "}"
-  else
-    echo 'mode hide
-hidden_state hide
-}'
-  fi
+
+  ## i'm running some automation which auto-unhides the bar constantly
+  ## and overlaps the bottom of windows, so for now, i'm unconditionally
+  ## displaying it. When that is done, remove the below echo and
+  ## uncomment the conditional below.
+  echo "}"
+
+  #   if [[ $secondary_out ]]; then
+#     echo "}"
+#   else
+#     echo 'mode hide
+# hidden_state hide
+# }'
+#   fi
+
 } >> ~/i3-myx.conf
 
 echo "bindsym \$mod+Shift+t move workspace to output ${move_outputs[*]}" >>~/i3-myx.conf