done
if (( i == 0 )); then
- echo "no dirs in "$cdirs""
+ echo "no dirs in cdirs=$cdirs"
return 0
fi
read -sr -N 1 input
# the unit hanging around in a failed state needing manual killing
# of the process.
sdrun_prefix=sudo
- sdrun_args="--uid "$(id -u)" --gid "$(id -g)" -E SSH_AUTH_SOCK=/run/openssh_agent"
+ sdrun_args="--uid $(id -u) --gid $(id -g) -E SSH_AUTH_SOCK=/run/openssh_agent"
fi
if [[ $cmd != /* ]]; then
# we need to pass a full path to systemd
fi
}
+d16fan() {
+ apt -y install thinkfan lm-sensors
+ modprobe -a w83795 w83627ehf
+ # from fsf ansible
+ cat << EOF > /etc/thinkfan.conf
+(20, 0, 55)
+(40, 50, 60)
+(85, 55, 65)
+(130, 60, 70)
+(175, 65, 75)
+(210, 70, 80)
+(255, 75, 32767)
+EOF
+ find /sys/ | grep 'temp[1-8]_input' | xargs -i echo hwmon {} >> /etc/thinkfan.conf
+ find /sys/module/w83795/drivers/*/*/pwm1 | sort | head -1 | xargs -i echo pwm_fan {} >> /etc/thinkfan.conf
+ systemctl restart thinkfan
+}
+
+
#### end fsf section
sk-p() {
[[ ! -L $f ]] && istext "$1" && [[ $(head -n1 "$1" 2>/dev/null) == '#!/bin/bash'* ]]
}
-# shellcheck with better defaults.
+# wrapper for shellcheck with better defaults.
sk() {
# see https://savannah.gnu.org/maintenance/fsf/bash-style-guide/ for justifications
local quotes others ret
info bash 'Basic Shell Features' 'Shell Expansions' 'Shell Parameter Expansion'
}
+btrfs() {
+ local log_path regex=' sub[^ ]* (del[^ ]*|create|snap|rescue|replace) | send | receive '
+ if [[ $EUID == 0 && $* =~ $regex ]]; then
+ mkdir -p /var/log/btrbk
+ log_path=/var/log/btrbk/$(date +%F_%H_%M_%S%:::z).log
+ printf "running: %s\n" "$*" | 'ts "%F %T" >>'$log_path
+ command btrfs "$@" |& pee cat 'ts "%F %T" >>'$log_path
+ else
+ command btrfs "$@"
+ fi
+}
brc3() {
source /a/c/brc3
bindpushb8
# for wireguard configs
- ssh iank@li.b8.nz conflink
+ ssh iank@li.b8.nz eval conflink \; ser reload wg-quick@wgmail
wrt-setup
}
xdg-settings set default-web-browser firefox.desktop
}
+
export BASEFILE_DIR=/a/bin/fai-basefiles
#export ANDROID_HOME=/a/opt/android-home
btrfs-snapshot-ro() {
btrfs property set -f -ts "$1" ro true
}
+
+mmdebstrap-ecne-noble-missing() {
+ local ecne ecne_prefix noble noble_prefix
+ noble_prefix=/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_noble
+ noble=$(echo ${noble_prefix}{,-security,-updates}_{main,universe}_binary-amd64_Packages)
+ for f in $noble; do
+ if [[ ! -s $f ]]; then
+ echo error: missing noble package lists. noble: $noble
+ return 1
+ ## 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
+ # gunzip Packages.gz
+ # mv Packages main
+ # gunzip -S .gz.1 Packages.gz.1
+ # fi
+ # noble="main Packages"
+ fi
+ done
+ ecne_prefix=/var/lib/apt/lists/archive.trisquel.org_trisquel_dists_ecne
+ ecne=$(echo ${ecne_prefix}{,-updates,-security}_main_binary-amd64_Packages)
+ for f in $ecne; do
+ if [[ ! -s $f ]]; then
+ echo error: missing ecne package lists. f: $f ecne: $ecne
+ return 1
+ fi
+ done
+ for dist in ecne noble; do
+ # thunderbird is just a way to get rid of its langpacks, since its main package depends on snap
+ { grep-dctrl -F package -v -r 'ubuntu\|zfs\|thunderbird\|snapd\|microcode\|^linux-' ${!dist} | grep-dctrl -s package -n -F depends,pre-depends -v snapd - ; if [[ $dist == noble ]]; then echo ubuntu-keyring; fi; } | sort >$dist
+ # for just debootstrapped packages:
+ #grep-dctrl -s package -n -F essential -r '^yes$' --or -F priority -r '^required\|important$' ${!dist} | sort >$dist
+ done
+ comm -13 ecne noble | tr '\n' ' ' | tee prefs-pkgs
+ cat >prefs <<EOF
+Package: *
+Pin: release n=noble,o=Ubuntu
+Pin-Priority: -100
+
+Package: $(cat prefs-pkgs)
+Pin: release n=noble,o=Ubuntu
+Pin-Priority: 500
+EOF
+ hr
+ { grep-dctrl -s package -n -F essential,priority -r '^yes\|required\|important$' $noble | grep -v ubuntu | tr '\n' ',' ; echo ubuntu-keyring ; } | tee pkgs
+
+}
+
+update-ecne-missing() {
+ mkc /t/mmchroot
+ mmdebstrap-ecne-noble-missing
+ cp prefs /b/fai/fai/config/files/etc/apt/preferences.d/ecne-missing/ECNE
+ s cp prefs /etc/apt/preferences.d/ecne-missing
+}
+mmdebstrap-ecne-noble() {
+ # note: can't use a tempdir because it is mounted nodev. command
+ # will succeed but only have 1 file in /dev, when several are
+ # expected. and not warn us about it.
+ mkc /t/mmchroot
+ mkdir r
+ cat >sources <<'EOF'
+deb http://archive.trisquel.org/trisquel/ ecne main
+deb http://archive.ubuntu.com/ubuntu/ noble main universe
+EOF
+ mmdebstrap-ecne-noble-missing
+
+ # normal sudo can't handle newlines in args
+ cat >mmdebstrap-cm <<EOF
+mmdebstrap --variant=custom --setup-hook='echo "$(cat prefs)" > "\$1"/etc/apt/preferences' --include=$(cat pkgs) ecne r ./sources
+EOF
+ s . mmdebstrap-cm
+
+ freeshdeb=freesh-archive-keyring_1.1_all.deb
+ if [[ ! -s r/tmp/$freeshdeb ]]; then
+ wget -P r/tmp https://linux-libre.fsfla.org/pub/linux-libre/freesh/pool/main/f/freesh-archive-keyring/$freeshdeb
+ fi
+ s chroot r dpkg -i /tmp/$freeshdeb
+ # use standard sources.list file that fai will later overwrite.
+ s mv r/etc/apt/sources.list.d/0000sources.list r/etc/apt/sources.list
+ rm r/tmp/$freeshdeb
+}
+
+# this does what fai's mk-basefile does, but not entirely as root and
+# with our alternate debootstrap
+ecne-basefile() {
+ local xtmp=r attributes="--xattrs --selinux --acls"
+ mmdebstrap-ecne-noble
+
+ s rm -f $xtmp/etc/hostname $xtmp/etc/resolv.conf \
+ $xtmp/var/lib/apt/lists/*_* $xtmp/usr/bin/qemu-*-static \
+ $xtmp/etc/udev/rules.d/70-persistent-net.rules \
+ $xtmp/var/lib/dbus/machine-id
+ s truncate -s0 $xtmp/etc/machine-id
+ s tar $attributes --numeric-owner --one-file-system -C r -cf - . | zstd -9 > /b/fai-basefiles/ECNE64.tar.zst
+ echo "WARNING: remove leftover /t/mmchroot"
+}
--- /dev/null
+[Service]
+# empty signifies to replace the existing value
+ExecStart=
+# because I don't have snap, this prints a message on startup. fine, but
+# it often gets into a loop of printing it every 15 seconds. I note that
+# debian's version is not compiled with snap support.
+ExecStart=/usr/bin/pipewire-pulse |& /usr/bin/sed '/^default: snap_get_audio_permissions/d'
- local_snap_list_cmds=()
tg_snaps=()
source_snaps=()
# but it doesn't show when a send has a parent and when it doesn't.
verbose=true; verbose_arg="-l trace"
force=false
-if [[ $PPID == 1 ]]; then
+if [[ $PPID == 1 || $INVOCATION_ID || $SYSTEMD_EXEC_PID ]]; then
# running as a service. we cant show progress in this case,
# but if we pass the arg, it will insert mbuffer into the command.
progress_arg=
fast=false
kd_spread=false
check_installed=false
+xlock=false
orig_args=("$@")
-temp=$(getopt -l check-installed,fast,pull-reexec,help 23acefikl:m:npqrs:t:vh "$@") || usage 1
+temp=$(getopt -l check-installed,fast,pull-reexec,help 23acefikl:m:npqrs:t:vxh "$@") || usage 1
eval set -- "$temp"
while true; do
case $1 in
# quit early, just btrbk, no extra remounting etc.
-e) early=true ;;
# avoids some default behaviors:
- # - no skipping hosts where xprintidle haven't been idle recently
# - exit if we can't ssh to 1 or more hosts
# - still set default hosts despite MAIL_HOST status
+ # - negates -x.
-f) force=true ;;
# skip various checks. when we run twice in a row for
# switch mail-host, no need to repeat the same checks again.
-v)
verbose=true; verbose_arg="-l trace"
;;
+ # exit if we have unlocked xscreensaver, to avoid interrupting machine in active use.
+ # -f turns this off.
+ -x) xlock=true ;;
-h|--help) usage ;;
--) shift; break ;;
*) die "Internal error!" ;;
if $fast; then
zone=$local_zone
else
- if ! zone=$(ssh root@$source date +%z); then
+ if ! ssh_info=$(ssh root@$source 'hostname && date +%z'); then
if $conf_only; then
echo "$0: warning: failed to ssh to root@$source"
else
die failed to ssh to root@$source
fi
fi
+ { read -r source_hostname; read -r zone; } <<<"$ssh_info"
if [[ $zone != "$local_zone" ]]; then
die "error: dont confuse yourself with multiple time zones. $h has different timezone than localhost"
fi
# idle, i dunno why, instead we are checking if the screen is locked,
# which is good enough.
#
- # This is a separate ssh because the command can fail and thatis ok.
- if ! $force; then
+ if ! $force && ! $xlock; then
locked=false
# note Invalid MIT-MAGIC-COOKIE-1 keyxscreensaver-command: can't open display :0 is expected if
# the system is locked by greeter.
else
locked=true
fi
+ fi
+ # This is a separate ssh because the command can fail and thatis ok.
+ if ! $force; then
if ! $locked; then
# Ignore this host. i sometimes use a non-main machine for
# testing or web browsing, knowing that everything will be wiped
## compress and copy logs in case a machine dies, we still have its logs.
bzip2 $log_path
for tg in ${targets[@]}; do
- # we generated
+ # we generated, so its our hostname.
m rsync --mkpath -a -f"- */" -f"+ *" /var/log/btrbk/ root@$tg:/var/log/btrbk/$HOSTNAME
done
if [[ $source ]]; then
- m rsync --mkpath -a -f"- */" -f"+ *" $source:/var/log/btrbk/ /var/log/btrbk/$source
+ m rsync --mkpath -a -f"- */" -f"+ *" $source:/var/log/btrbk/ /var/log/btrbk/$source_hostname
fi
mexit $ret
}
pre="mount-latest-subvol:${SSH_CLIENT:+ $HOSTNAME:}"
+log_path=/var/log/btrbk/$(date +%F_%H_%M_%S%:::z).log
tu() {
while read -r line; do
printf "$pre %s\n" "$*"
fi
}
+b() {
+ printf "$pre running: %s\n" "$*" |& pee cat 'ts "%F %T" >>'$log_path
+ "$@" |& pee cat 'ts "%F %T" >>'$log_path
+}
m() {
if $verbose; then
printf "$pre %s\n" "$*"
fi
"$@"
}
-x() {
- printf "$pre %s\n" "$*"
- "$@"
-}
mnt() {
dir=$1
##### end command line parsing ########
ret=0
+mkdir -p /var/log/btrbk
##### begin setup fstab for subvols we care about ######
cd $root_dir
if [[ -e $vol ]]; then
if [[ $vol == qd ]]; then
- m btrfs sub del qd
+ b btrfs sub del qd
else
leaf=$vol.leaf.$(date +%Y-%m-%dT%H:%M:%S%z)
- m mv $vol $leaf
- m btrfs property set -ts $leaf ro true
+ b mv $vol $leaf
+ b btrfs property set -ts $leaf ro true
### begin check if leaf is different, delete it if not ###
parentid=$(btrfs sub show $leaf | awk '$1 == "Parent" && $2 == "UUID:" {print $3}')
# example output of no differences:
# snapshot ./qrtest uuid=c41ff6b7-0527-f34d-95ac-190eecf54ff5 transid=2239 parent_uuid=64949e1b-4a3e-3945-9a8e-cd7b7c15d7d6 parent_transid=2239
echo suspected identical: $bsub $leaf
- x btrfs sub del $leaf
+ b btrfs sub del $leaf
fi
fi
### end check if leaf is different, delete it if not ###
for leaf in ${leaf_vols[@]}; do
leaf_time=$(date -d ${leaf#"$vol".leaf.} +%s)
if (( leaf_limit_time > leaf_time || ( leaf_new_limit_time > leaf_time && count > 30 ) )); then
- x btrfs sub del $leaf
+ b btrfs sub del $leaf
fi
count=$((count-1))
done
# Note, we make a few assumptions in this script, like
# $d was not a different subvol id than $vol, and
# things otherwise didn't get mounted very strangely.
- m btrfs sub snapshot $fresh_snap $vol
+ b btrfs sub snapshot $fresh_snap $vol
for dir in $d ${binds[@]}; do
m mnt $dir
done
if ! kill-dir TERM TERM TERM INT INT HUP HUP TERM TERM TERM INT INT HUP HUP; then
if $force; then kill-dir KILL; fi
fi
- m btrfs sub del $dir
+ b btrfs sub del $dir
fi
- m btrfs sub snapshot $fresh_snap $dir
+ b btrfs sub snapshot $fresh_snap $dir
rm -f /nocow/btrfs-stale/$vol
done
# to root, and it allows us to have a working ssh when X isnt available,
# eg, in an ssh shell. confirm for regular user provides some protection
# that a rouge user program cant use my ssh key.
- sed 's,^AddKeysToAgent confirm,AddKeysToAgent yes,;/^UserKnownHostsFile /d' $user_ssh_dir/config >/root/.ssh/confighome
+ #
+ # HOME is not set in systemd services
+ sed 's,^AddKeysToAgent confirm,AddKeysToAgent yes,;s,\${HOME},/root,g;/^UserKnownHostsFile /d' $user_ssh_dir/config >/root/.ssh/confighome
# having a different control path avoids the problem of
# forgetting to use confighome, and then after specifying it,
# it uses the multiplex socket, which means that the different
m btrbk-run -v --fast $bbk_args $force_arg $incremental_arg -m /o || ret=$?
if (( ret )); then
bang="███████"
- e $bang failed btrbk of /o. restoring old host as primary
+ e $bang failed btrbk of /o. restoring old host as MAIL_HOST, new host is still HOST2
if ! m $old_shell /a/exe/primary-setup localhost; then
die "due to failed btrbk of /o, we tried to restore old host as primary, but then we failed at that too. To resolve: Fix & rerun switch-mail-host, or fix and rerun primary-setup localhost on old shell so you have a working mail server and then rerun switch-mail-host."
fi
found_pids=true
fuser -$sig -mvk $dir
fi
- sleep .5
+ sleep .8
if ! $found_pids; then
return 0
fi
return 1
}
+umount-try() {
+ local ret=0
+ umounted=false
+ m umount -R $1 || ret=$?
+ if (( ret == 0 )); then
+ umounted=true
+ unmounted+=($dir)
+ fi
+ return $ret
+}
+
# leaf function. others are just used by this one.
umount-kill() {
dir=$1
if mountpoint -q $dir; then
- if m umount -R $dir; then
- unmounted+=($dir)
- else
+ if ! umount-try $dir; then
if ! kill-dir TERM TERM TERM INT INT HUP HUP TERM TERM TERM INT INT HUP HUP; then
- if $force; then kill-dir KILL; fi
+ if [[ $force ]] && $force; then kill-dir KILL; fi
fi
- if m umount -R $dir; then
- unmounted+=($dir)
- else
+ if ! umount-try $dir; then
+ # 2024-08, i've been noticing emacs randomly holding open /a
+ # without its pid being found by fuser or lsof.
+ # i'm on commit b9da5ee06f2e4ae807336dd6a641ae797831d097
+ if m pkill -xf 'emacs --daemon'; then
+ sleep 2
+ umount-try $dir ||:
+ fi
+ fi
+ if ! $umounted; then
echo "$0: failed to umount $dir"
umount_ret=false
ret=1
[Service]
Type=oneshot
ExecStartPre=/a/exe/install-my-scripts
-ExecStart=/usr/local/bin/sysd-mail-once -t daylert@iankelling.org btrbk /usr/local/bin/btrbk-run
+ExecStart=/usr/local/bin/sysd-mail-once -t daylert@iankelling.org btrbk /usr/local/bin/btrbk-run -x
ExecStartPost=/bin/sleep 1
ExecStartPost=/a/exe/install-my-scripts
wondershaper
xawtv
xbacklight
- xdg-desktop-portal-lxqt
+ # not yet in aramo. todo: upgrade or make distro version dependent.
+ #xdg-desktop-portal-lxqt
xdot
# needed for some i3 hacks
xdotool