# 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
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)
# 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 )
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.
{
cat <<EOF
+Host ${work_hosts[@]}
+User root
+IdentityFile ~/.ssh/work
+
Host ${nonroot_hosts[@]}
User iank
IdentityFile ~/.ssh/home
# 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
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.
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
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
# 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
# usage: pass encoded string on stdin
url-decode() {
python3 -c "import sys; from urllib.parse import unquote; print(unquote(sys.stdin.read()));"
- }
+}
[Service]
ExecStartPre=/a/c/znc-start-delay
+Restart=always
+RestartSec=30
+TimeoutStartSec=300
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
done
}
+
# Note, this depends on write-config being called first.
#
# Delete any subvols on the receiving host that don't exist on the
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 ))
# 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=()
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.
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() {
# echo COMMAND then run it.
m() { printf "+ %s\n" "$*" >&2; "$@"; }
+
# mb, maybe. echo args if they fail.
mb() {
local ret=0
# 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...]
#
#
# - 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).
#
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
}
### 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
fi
}
+#echo "$*" >>/tmp/g.log
g "$@"
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
--- /dev/null
+ifconfig-push 10.5.5.99 255.255.255.0
--- /dev/null
+[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
#
#&! 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.
{
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