From: Ian Kelling Date: Wed, 7 Oct 2026 09:55:41 +0000 (-0400) Subject: lots of stuff, fixes and features X-Git-Url: https://iankelling.org/git/?a=commitdiff_plain;h=5b2009e2ee56afddec87bd201c1052799ada6a50;p=distro-setup lots of stuff, fixes and features --- diff --git a/.perlcriticrc b/.perlcriticrc index 178402f..c8a207d 100644 --- a/.perlcriticrc +++ b/.perlcriticrc @@ -1,2 +1,24 @@ +# false positives: tidy, checked syscalls. rest are preferences. + +[-CodeLayout::RequireTidyCode] +[-InputOutput::RequireCheckedSyscalls] +[-ValuesAndExpressions::ProhibitVersionStrings] +[-Modules::ProhibitAutomaticExportation] +[-Variables::ProhibitPackageVars] +[-ControlStructures::ProhibitPostfixControls] +[-ValuesAndExpressions::ProhibitImplicitNewlines] +[-ValuesAndExpressions::RequireQuotedHeredocTerminator] [-Subroutines::RequireArgUnpacking] [-Subroutines::RequireFinalReturn] +[-RegularExpressions::RequireExtendedFormatting] +[-ControlStructures::ProhibitCascadingIfElse] +[-Variables::ProhibitConditionalDeclarations] +[-Modules::RequireBarewordIncludes] +[-Variables::ProhibitPunctuationVars] + +[Subroutines::ProhibitExcessComplexity] +add_themes = complex_mess +[ControlStructures::ProhibitDeepNests] +add_themes = complex_mess +[Subroutines::ProhibitManyArgs] +add_themes = complex_mess diff --git a/brc b/brc index 042bdb6..09850c4 100644 --- a/brc +++ b/brc @@ -722,7 +722,7 @@ jdo() { $sdrun_prefix systemd-run $sdrun_args --unit "$unit_name" --wait --collect "$cmd" "$@" || ret=$? # The sleep lets the journal output its last line # before the prompt comes up. - sleep .5 + sleep 1 kill $jr_pid &>/dev/null ||: unset jr_pid fg &>/dev/null ||: @@ -1817,22 +1817,22 @@ faf() { -o -name .hg -prune -o -name .editor-backups -prune \ -o -name .undo-tree-history -prune \) \! -type d 2>/dev/null } -# fas = find all shebang. filter by the last word in the shebang path +# fas = find all shebang. filter by the last word in the shebang path. # usage: $0 INTERPRETER_BINARY_NAME [FIND_INITIAL_ARGS...] fas() { local name="$1" shift - find "$@" -not \( -name .svn -prune -o -name .git -prune \ + find "$@" \! \( -name .svn -prune -o -name .git -prune \ -o -name .hg -prune -o -name .editor-backups -prune \ -o -name .undo-tree-history -prune \) \! -type d \ -exec awk 'FNR==1 && /^#![^ ]*\/'"$name( |$)/ {print FILENAME; nextfile}" {} + 2>/dev/null - } +} # like faf, but sort by modification time. like lt() faft() { find "$@" -not \( -name .svn -prune -o -name .git -prune \ -o -name .hg -prune -o -name .editor-backups -prune \ - -o -name .undo-tree-history -prune \) \! -type d \ + -o -name .undo-tree-history -prune \) -type f \ -printf "%T@ %P\n" | sort -n | cut -d' ' -f2- } @@ -2659,7 +2659,7 @@ pubip6() { wget -6 -q -O- https://icanhazip.com; } whatismyip() { pubip; } -q() { # quietly start / launch a program +q() { # quietly start / launch a program, as long as it doesn't fail within a second. "$@" &> /dev/null & disown # online, I ran into a version that runs in a subshell with ( ), I # suppose that might quiet some programs that try to talk to the tty @@ -2840,6 +2840,11 @@ ri() { "$@" | sponge "$file" } +# in-place perltidy with settings i like. +pltidy() { + ri perltidy -i=2 -l=200 -pt=2 -nsfs -ce -conv -st --valign-exclusion-list='if unless and or err for foreach while until' "$@" +} + # rsync with nice defaults. # scp is a bit insecure and deprecated. sp() { @@ -4963,16 +4968,6 @@ lswc-avg() { } -# usage $0 PID... -maxpri() { - # we try process group (-g, -P) to hit related processes. If this fails, fall back to pid: (-p, -p) - if ! s renice -20 -g "$@"; then - m s renice -20 -p "$@" - m s ionice -c1 -n0 -p "$@" - return 0 - fi - s ionice -c1 -n0 -P "$@" -} # usage $0 PID... minpri() { @@ -4981,9 +4976,11 @@ minpri() { m s ionice -c3 -p "$@" return 0 fi - s ionice -c3 -P "$@" + m s ionice -c3 -P "$@" } -# Prefix for launching a command: + + +# Prefix for launching a command (missing the : # shellcheck disable=SC2034 # false positive maxpri="s nice -n-40 ionice -c1 -n0" # shellcheck disable=SC2034 # false positive @@ -5025,11 +5022,318 @@ loc() { wg-log-on() { e module wireguard +p | s tee /sys/kernel/debug/dynamic_debug/control - } +} wg-log-off() { e module wireguard -p | s tee /sys/kernel/debug/dynamic_debug/control } + +### begin debug-setx related functions ### +# +# usage: debug-setx +# +# Print executing commands like "set -x", but: +# +# - Skips printing many boring/redundant lines. There are related +# functions below to modify/toggle what gets printed. +# +# - Related function h() to prompt before executing printed command. +# +# Printing of uninteresting commands can be limited: +# +# 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). +# +# There is a hard-coded list of commands to skip or maybe skip. You can +# improve this. +# +debug-setx() { + local existing_debug_trap + + # Note on commands we skip printing: + # - read ends up being what is shown for 'while read' loops. + + # for inheriting debug in subshells + shopt -s extdebug + + debug_prompt=false + debug_skip=false + debug_force_print=false + + existing_debug_trap=$(trap -p DEBUG 2>&1) + if [[ $existing_debug_trap && $existing_debug_trap != *_debug-setx-func ]]; then + trap "$existing_debug_trap; _debug-setx-func" DEBUG + else + trap _debug-setx-func DEBUG + fi +} +# internal function called via debug-setx trap. +_debug-setx-func() { + local doprint=false random_delimiter func cmd col debug_cmd + + if [[ $debug_max_stack_depth ]]; then + 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=99999 + fi + + if [[ $BASH_SUBSHELL != [01] ]]; then + return 0 + fi + + if $debug_skip; then + debug_skip=false + return 0 + fi + + if $debug_prompt; then + doprint=true + fi + + if $debug_force_print; then + debug_force_print=false + doprint=true + fi + + if $debug_print_default; then + + ## block for debug_print_funcs + if ! $doprint; then + for func in ${debug_print_funcs[@]}; do + if [[ $func == "${FUNCNAME[1}" ]]; then + doprint=true + break + fi + done + fi + + ## block for default command & function ignoring + if ! $doprint && (( ${#FUNCNAME[*]} <= funcname_count_max )); then + # debug + #e "${FUNCNAME[*]} ${#FUNCNAME[*]} <= $funcname_count_max" + case $BASH_COMMAND in + e\ *|err\ *|echo\ *|printf\ *|read\ *|h|ux|ux\ *) + : ;; + for\ *) + # try to print just the first for loop iteration. + _debug_setx_cur_for="$BASH_COMMAND ${BASH_LINENO[0]} ${FUNCNAME[1]}" + if [[ $_debug_setx_cur_for != "$_debug_setx_last_for" ]]; then + doprint=true + fi + _debug_setx_last_for="$_debug_setx_cur_for" + ;; + *) + doprint=true + ;; + esac + fi + + fi + + if $doprint; then + # Expanding $1 will be empty, so skip expansion in that case, and some others. + # + # TODO: we should be able to grab $1 from the function tracing facilities. + # + # Note, we could split the command up and expand other parts + # but I'm not going to bother. + if [[ $BASH_COMMAND != *\$[0-9]* && $BASH_COMMAND != *\`* && $BASH_COMMAND != *\$\(* && $BASH_COMMAND == *\$* ]]; then + random_delimiter=$RANDOM$RANDOM$RANDOM + # shellcheck disable=SC1003 + _d="$BASH_COMMAND" _d="${_d//'\\'/SUBfopguensOfRifejmu${random_delimiter}SUB}" _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//SUBfopguensOfRifejmu${random_delimiter}SUB/'\\\\'}" + cmd="${_d@P}" + else + cmd="$BASH_COMMAND" + fi + [[ $COLUMNS ]] || { _s=$(stty size); COLUMNS=${_s#* }; } + if [[ $COLUMNS == *[0-9]* ]]; then + # generally fill up 2 rows + col=$(( COLUMNS * 2 - 20 )) + else + col=150 + fi + if (( ${#cmd} > col )); then + cmd="$(( ${#cmd} - col)) cut: ${cmd:0:col}" + fi + echo "+ $cmd" >&2 + fi + + if $debug_prompt; then + # we can type in commands here to inspect the program state. + read -r -e -p "DEBUG $ " debug_cmd + while [[ $debug_cmd ]]; do + eval $debug_cmd + read -r -e -p "DEBUG $ " debug_cmd + done + debug_prompt=false + fi +} + +# usage: ux [COMMAND...] +# +# disable/unset debug-setx default command printing. Runs COMMAND if +# given. Command arg exists only because the args would be otherwise +# unused. +ux() { + debug_print_default=false + if [[ $1 ]]; then "$@"; fi +} + +# usage: u1 [COMMAND...] +# +# Disable debug-setx printing just for the next command. +u1() { + # we have this strange logic because [[ is a command, easier to not + # have that be between debug_skip=true and $@ and trigger a debug + # trap. + if [[ $1 ]]; then + debug_skip=true + "$@" + else + debug_skip=true + fi +} + +# usage: dx [COMMAND...] +# +# Undo ux() and reenable debug-setx printing. +dx() { + if [[ $1 ]]; then + debug_print_default=true + "$@" + else + debug_print_default=true + fi +} + +# usage: d1 [COMMAND...] +# +# For just one command, reenable debug-setx printing. +d1() { + if [[ $1 ]]; then + debug_force_print=true + "$@" + else + debug_force_print=true + fi +} + + + +# usage: setx-func [FUNCTION...] +# +# Do debug-setx printing within current function or FUNCTION(s) even +# when called with function stack size greater than +# $debug_max_stack_depth. +setx-func() { + local new_func new_funcs found existing_func + if [[ ! -v debug_print_funcs ]]; then + debug_print_funcs=() + fi + + e "${FUNCNAME[*]}" + if [[ $1 ]]; then + new_funcs="$*" + else + new_funcs="${FUNCNAME[0]}" + fi + for new_func in $new_funcs; do + found=false + for existing_func in ${debug_print_funcs[@]}; do + if [[ $existing_func == "$new_func" ]]; then + found=true + break + fi + done + if $found; then + break + fi + debug_print_funcs+=($new_func) + done +} + +### 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 + + # * stuff that makes sense to be at the end # note, if we unset IFS, that will mess up completion scripts which diff --git a/brc2 b/brc2 index 9f43626..c9ac4f1 100644 --- a/brc2 +++ b/brc2 @@ -1016,7 +1016,7 @@ btrbk-host-debug-show-host() { # Alt is just the other host that takes snapshots # besides the local host. btrbk-host-debug() { -local host remote alt f + local host remote alt f remote=b8.nz alt=sywg.b8.nz @@ -1237,7 +1237,7 @@ lipush() { /p/c/subdir_files ) a="-ahviSAXPH --specials --devices --delete --delete-excluded --relative --exclude-from=/p/c/li-rsync-excludes" - for h in li je bk; do + for h in li bk; do m s rsync "$@" $a ${fs[@]} /p/c/machine_specific/$h root@$h.b8.nz:/ ## only li is debian11 #p[0]=/a/opt/emacs-trisuqel10 @@ -1252,8 +1252,8 @@ bkpush() { local -a fs local -i ret=0 fs=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts} - /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter - ) + /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter + ) a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes" ret=0 m rsync "$@" $a ${fs[@]} /p/c/machine_specific/bk root@bk.b8.nz:/ || ret=$? @@ -1264,8 +1264,8 @@ jepush() { # no emacs. for running faster. local -a fs local -i ret=0 fs=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts} - /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter - ) + /a/f/ans/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter + ) a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes" ret=0 @@ -2041,7 +2041,7 @@ host-info-all() { bindpushb8 # for wireguard configs - ssh iank@li.b8.nz "conflink; ser reload wg-quick-mail" + ssh iank@li.b8.nz "conflink; ser reload wg-quick@mail" wrt-setup } @@ -2068,7 +2068,7 @@ hiup() { for h in ${root_hosts[@]}; do root_hosts+=(${h}ex) done - root_hosts+=(cmc) + root_hosts+=(cmc wrtap w33) work_hosts=(10.8.0.97 10.8.0.99) @@ -2237,6 +2237,26 @@ WantedBy=multi-user.target EOF done + + cat >/p/c/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf <<'EOF' +# generated by hiup +authoritative; +#option dhcp-max-message-size 2048; +use-host-decl-names on; + +subnet 10.0.0.0 netmask 255.255.0.0 { + range 10.0.0.100 10.0.0.199; + option routers 10.0.0.1; + option domain-name "b8.nz"; + option domain-search "b8.nz"; + option domain-name-servers 8.8.8.8; + option ntp-servers 0.ubuntu.pool.ntp.org, 1.ubuntu.pool.ntp.org, ntp.ubuntu.com; +} + +default-lease-time 600; +max-lease-time 7200; +EOF + for host in ${!vpn_ips[@]}; do if [[ ${root_hosts_a[$host]} ]]; then continue @@ -2259,6 +2279,7 @@ EOF echo "EOF" } | u /p/c/ptr-data + # this is for old setup where dhcp is done by cmc. { echo "cat <>/p/c/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf </dev/null; then s ip netns add nonet fi - mns $ns --net=/var/run/netns/nonet sudo -E -u iank /bin/bash + user=$USER + env-tmpf bash + mns-setup $ns + m sudm /usr/bin/nsenter --mount=/root/mount_namespaces/$ns --net=/var/run/netns/nonet sudo -u iank -i bash -c ". $tmpf" lomh } @@ -2950,7 +2986,17 @@ s/^[^ ]*\.txt:\((.{2}).(.{2}).(.{4}) (.{8}) (.{2})\)?/\3-\1-\2_\4_\5/' \ # my profanity # +# usage: $0 [weeks] myprof() { + local weeks + if [[ $1 ]]; then + weeks=$1 + elif [[ $(date +%A) == Monday ]]; then + weeks=2 + else + weeks=5 + fi + pushd /home/iank/.local/share/profanity/chatlogs/iank_at_fsf.org/rooms/office_at_conference.fsf.org logs=(*) @@ -2966,11 +3012,7 @@ myprof() { i=0 fi # usually do this on monday, sometimes later - if [[ $(date +%A) == Monday ]]; then - min_date=$(date -d 'monday 2 weeks ago' +%s) - else - min_date=$(date -d 'monday 5 weeks ago' +%s) - fi + min_date=$(date -d "monday $weeks weeks ago" +%s) for (( ; i < logcount; i++ )); do log_base=${logs[$i]} day_logs=() @@ -3674,7 +3716,8 @@ servicepid() { # could just get this in the first place, but i don't know if that # is always the case. procsf=$dir/${unit%.service}.service/cgroup.procs - if [[ -s $procsf ]]; then + # note: ls will show the file as empty even though it isn't + if [[ -e $procsf ]]; then pid=$(head -n1 $procsf) else pid= @@ -3887,6 +3930,7 @@ vpncmdroot() { vpni() { local n="$1" ser_suf=tr if [[ $n ]]; then ser_suf=nn; fi + vpnc $n # m sudo nsenter --net=/var/run/netns/client sudo -u iank -i bash # for just the netns sdncmd wg-quick-$ser_suf@client$n.service bash } @@ -4047,9 +4091,11 @@ vpnc() { local n="$1" ser_suf=tr if [[ $n ]]; then ser_suf=nn; fi unit=wg-quick-$ser_suf@client$n - sudo -v + if [[ $EUID != 0 ]]; then + sudo -v + fi if [[ $(systemctl is-active $unit) != active ]]; then - s systemctl start $unit + m s systemctl start $unit sleep 1 fi } @@ -4358,6 +4404,16 @@ else alias rg=grr fi +# find all perl files +fapl() { + fas perl \! -name '*.*'; faf \( -name '*.pl' -o -name '*.pm' \) +} + +# rg perl files +rgpl() { + rg "$@" $(fapl) +} + # rg with respecting vcs ignore files rgv() { local path_arg ret=0 diff --git a/conflink b/conflink index b303d53..0948c24 100755 --- a/conflink +++ b/conflink @@ -273,6 +273,8 @@ case $user in etc/systemd/resolved.conf.d/*) restart_services[systemd-resolved]=t ;; + # todo: this isnt working + etc/dhcp/dhcpd.conf) restart_services[isc-dhcp-server]=t ;; esac # Previously did this with tar, but it doesn't # update directory permissions. diff --git a/distro-end b/distro-end index 488075c..8423458 100755 --- a/distro-end +++ b/distro-end @@ -1015,6 +1015,16 @@ if [[ -e /p/c/machine_specific/$HOSTNAME/filesystem/etc/openvpn/client/hole.crt sgo openvpn-client@hole fi +case $HOSTNAME in + $d_host) + sgo frodo-route + sgo isc-dhcp-server + # Avoid the dhcp on other hosts. it seems static ips could be + # configured but i'm not bothering. + pi dropbear-initramfs + ;; +esac + ############# begin syncthing setup ########### case $HOSTNAME in $d_host) @@ -1584,7 +1594,8 @@ m /a/bin/buildscripts/textern #m /a/bin/buildscripts/alacritty #m /a/bin/buildscripts/kitty -pi-nostart virtinst virt-manager +# qemu & zsync are quickemu dependencies +pi-nostart virtinst virt-manager qemu-system zsync soff libvirtd # i cant if this is whats causing it to start even though # its disabled. note: it leaves around dnsmasq instances even @@ -2016,12 +2027,14 @@ esac # # # initial config goes to /home/iank/.config/gh -curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ - && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ - && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ +curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ + && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ && sudo apt-get update \ && sudo apt-get install gh -y +# fix old path on old computers. +sudo sed -ri 's,/usr/share/key,/etc/apt/key,' /etc/apt/sources.list.d/github-cli.list ### end gh #### @@ -2033,14 +2046,12 @@ if [[ ! -e /etc/apt/sources.list.d/pgdg.sources ]]; then pi postgresql-common sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y noble pi-nostart postgresql-$ver postgresql-doc-$ver - # when we run it, do: - #sudo -u postgres createuser -d iank sudo usermod -a -G postgres iank if ! out=$(psql -XAtq -Pfieldsep=' ' -vON_ERROR_STOP=on postgres <<<"select 1 from pg_user where usename = 'iank';" 2>/dev/null) || [[ $out != 1 ]]; then sudo -u postgres createuser -d iank fi # initial db creation with: - # createdb -O iank db_name + # createdb -O iank dl e "vm.hugetlb_shm_group=$(getent group postgres|awk -F : '{print $3}')" | sd /etc/sysctl.d/80-iank-hugepage-postgres.conf sudo sysctl -p/etc/sysctl.d/80-iank-hugepage-postgres.conf diff --git a/dynamic-ip-update b/dynamic-ip-update index 1238451..16180ec 100755 --- a/dynamic-ip-update +++ b/dynamic-ip-update @@ -85,21 +85,22 @@ main() { exit 0 fi fi + + + + read -r _ _ gateway _ ifdev _ <<<"$tmp" - case $gateway in - 10.2.0.1) - dyndomain=b8.nz - # This domain is for any case where we want some different - # configuration based on lan vs wan. For right now, the only use - # is for ssh config to use port forwarding ports on the wan - # domain. - dyndomain_internet=i.b8.nz - ;; - *) - return 0 - ;; - esac + if [[ $HOSTNAME == frodo || $gateway == 10.2.0.1 ]]; then + dyndomain=b8.nz + # This domain is for any case where we want some different + # configuration based on lan vs wan. For right now, the only use + # is for ssh config to use port forwarding ports on the wan + # domain. + dyndomain_internet=i.b8.nz + else + return 0 + fi # We check if we are at home by testing gateway ssh # fingerprint. However, if we found in the past that we are, I dont @@ -115,9 +116,12 @@ main() { printf "%s\n" "$newbytes" >/dev/shm/dynamic-ip-update-state fi fi - if ! $athome && timeout -s 9 5 ssh-keyscan -p 2220 -t rsa $gateway 2>/dev/null | grep -qFx "[$gateway]:2220 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCH+/h1dGEfKEusBblndU2e6QT4wLCm5+yqr/sqh/0X9YfjR7BfWWm8nNmuP55cYc+Wuf5ljB1H1acXEcsl1y8e0j3agHfF0V74FE1N1zz5nn2Ep8NHnmqgEhza38ZxMPh+4p3X7zklEKU7+3SzybKBi8sg0wLzlS2LM0JaUN80zR2sK11Kye3dURUXPk78u5wodOkgcEYRwSYaDMJlUzWP+poRXIDJwFaMQnwmxbl/c84yOyaU0x/d6hFwoRscWecihX+vvBNeSyxR4xr2HDOyUWwJkctyAgt2p7w3tfkXOKcCRzTAjGVIMQLTvo0sG/yJbcyHoEFdFybCsgDvfyYn"; then - athome=true - awk '$1 == "'$ifdev':" {print $2 + $10}' /proc/net/dev > /dev/shm/dynamic-ip-update-state + + if ! $athome; then + if [[ $HOSTNAME == frodo ]] || timeout -s 9 5 ssh-keyscan -t ed25519 $gateway 2>/dev/null | grep -qFx "$gateway ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHggN4OjyqJCF5lmqMEBmFAyTFvNruZgNqxj0a9ztls"; then + athome=true + awk '$1 == "'$ifdev':" {print $2 + $10}' /proc/net/dev > /dev/shm/dynamic-ip-update-state + fi fi diff --git a/filesystem/etc/docker/daemon.json b/filesystem/etc/docker/daemon.json new file mode 100644 index 0000000..4d95dc2 --- /dev/null +++ b/filesystem/etc/docker/daemon.json @@ -0,0 +1 @@ +{ "default-address-pools": [ { "base": "172.31.0.0/20", "size": 24 } ] } diff --git a/filesystem/etc/etckeeper/commit.d/20iank-mirror b/filesystem/etc/etckeeper/commit.d/20iank-mirror new file mode 100644 index 0000000..7870e2e --- /dev/null +++ b/filesystem/etc/etckeeper/commit.d/20iank-mirror @@ -0,0 +1,25 @@ +#!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to change +# to a recommended GPL license. + +# Copyright 2025 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# for saving files outside of /etc with etckeeper + +rsync -a --relative --mkpath /var/lib/exim4/config.autogenerated /etc/etckeeper/fsmirror/ diff --git a/filesystem/etc/profile.d/environment.sh b/filesystem/etc/profile.d/environment.sh index 5457716..ecd724f 100644 --- a/filesystem/etc/profile.d/environment.sh +++ b/filesystem/etc/profile.d/environment.sh @@ -47,7 +47,8 @@ export PITHOSFLY_SAVE_DIR=/a/pandora_rips4 # I also set this in # /a/c/filesystem/etc/systemd/system.conf.d/tz.conf # https://blog.packagecloud.io/eng/2017/02/21/set-environment-variable-save-thousands-of-system-calls/ -export TZ=:/etc/localtime +# # However, those instructions backfired because emacs erc didn't understand the value +# export TZ=:/etc/localtime # ubuntu starts gpg agent automatically with /etc/X11/Xsession.d/90gpg-agent. # fedora doesn't, which left me to figure this out, and google was no help. diff --git a/filesystem/etc/systemd/system.conf.d/tz.conf b/filesystem/etc/systemd/system.conf.d/tz.conf index dcfba45..f843501 100644 --- a/filesystem/etc/systemd/system.conf.d/tz.conf +++ b/filesystem/etc/systemd/system.conf.d/tz.conf @@ -1,3 +1,4 @@ [Manager] -DefaultEnvironment=TZ=:/etc/localtime +# see /b/ds/filesystem/etc/profile.d/environment.sh +#DefaultEnvironment=TZ=:/etc/localtime # also set in profile.d/environment.sh with explanation there diff --git a/filesystem/usr/local/bin/frodo-route b/filesystem/usr/local/bin/frodo-route new file mode 100755 index 0000000..85d728f --- /dev/null +++ b/filesystem/usr/local/bin/frodo-route @@ -0,0 +1,36 @@ +#!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to change +# to a recommended GPL license. + +# Copyright 2025 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR + +if [[ $EUID != 0 ]]; then + echo "$0: error: expected to be root." + exit 1 +fi + + +rule="POSTROUTING -s 10.0.0.0/16 -o eth1 -j MASQUERADE" + +if ! iptables -t nat -C $rule &>/dev/null; then + iptables -t nat -I $rule +fi diff --git a/filesystem/usr/local/bin/i3-chat b/filesystem/usr/local/bin/i3-chat index 13034c5..ce2e24a 100755 --- a/filesystem/usr/local/bin/i3-chat +++ b/filesystem/usr/local/bin/i3-chat @@ -23,7 +23,7 @@ i3-msg "workspace 4" # start emacs daemon for profanity/znc if it doesnt exist. -id=$(i3-msg -t get_tree | jq -e '.. | select(.name?) | select(.name | test("^iznc ")).id') +id=$(i3-msg -t get_tree | jq -e '.. | select(.name?) | select(.name | test("^e-profanity ")).id') if [[ ! $id ]]; then emacsclient -s profanity -nc &>/dev/null diff --git a/filesystem/usr/local/bin/imidpri b/filesystem/usr/local/bin/imidpri new file mode 100755 index 0000000..d5b7398 --- /dev/null +++ b/filesystem/usr/local/bin/imidpri @@ -0,0 +1,92 @@ +#!/bin/bash + +# usage: [-v] -d|-m PID|PGREP_FULL_REGEX... +# +# -d Set pids to default priority. +# -m Set pids to max priority. +# +# -v = verbose output. + +[[ $EUID == 0 ]] || exec sudo "${BASH_SOURCE[0]}" "$@" + + +. /a/c/fsf-script-lib + +maxpri() { + for pid; do + chrt --all-tasks --rr --reset-on-fork --pid 50 $pid + done + # we try process group (-g, -P) to hit related processes. If this fails, fall back to pid: (-p, -p) + if ! renice -20 -g "$@"; then + renice -20 -p "$@" + # c1 = realtime, it can starve other processes, which is probably + # not something I'd probably want. + ionice -c2 -n0 -p "$@" + return 0 + fi + ionice -c2 -n0 -P "$@" +} + + +midpri() { + local pid + local -a tids + for pid; do + chrt --all-tasks --other --pid 0 $pid + for task in /proc/$pid/task/*; do + tids+=("${task##*/}") + done + done + renice -n 0 -p "${tids[@]}" + ionice -c 0 -p "${tids[@]}" +} + +#verbose=false +if [[ $1 == -v ]]; then + set -x + #verbose=true + shift +fi + + +if [[ $1 == -m ]]; then + max=true +elif [[ $1 == -d ]]; then + max=false +else + err "invalid 1st cli arg" + exit 1 +fi +shift + +maxpids=() +midpids=() + +while [[ $1 ]]; do + unset pids # not needed, just for clarity. + if [[ $1 == -m ]]; then + max=true + elif [[ $1 == -d ]]; then + max=false + else + if [[ $1 =~ $uint_regex ]]; then + pids=$1 + else + pids=$(pgrep -d ' ' -f "$1") + fi + if $max; then + maxpids+=( $pids ) + else + midpids+=( $pids ) + fi + fi + shift +done + +if (( ${#maxpids[@]} )); then + maxpri ${maxpids[@]} +fi + +if (( ${#midpids[@]} )); then + midpri ${midpids[@]} +fi diff --git a/filesystem/usr/local/bin/mon-brightness-cycle b/filesystem/usr/local/bin/mon-brightness-cycle index 32ac218..0c59e23 100755 --- a/filesystem/usr/local/bin/mon-brightness-cycle +++ b/filesystem/usr/local/bin/mon-brightness-cycle @@ -27,10 +27,23 @@ state_f=/tmp/user/1000/tmp_mon_bright.KROSZousbE low_level=70 set-bright() { - ddcutil --display 1 setvcp 10 $1 + # loop using proper detection + #for dnum in ${displays[@]}; do + # + for (( dnum=display_count; dnum >= 1; dnum-- )); do + # note: I tried running this in the background, but it turns out a 2nd call in parallel + # breaks the 1st call. + ddcutil --display $dnum setvcp 10 $1 + done echo $1 >$state_f } +# proper detection, but slow, like .75 seconds. +#displays=( $(ddcutil detect -t| sed -rn 's/^Display[[:space:]]+([0-9]+)[[:space:]]*$/\1/p' | tac) ) +# instead: +declare -i display_count +display_count=$(xrandr | awk '$2 == "connected" {count++} END {print count}') + if [[ -s $state_f ]]; then cur_bright=$(cat $state_f) # echo "state_f: $cur_bright" # debug diff --git a/filesystem/usr/local/bin/mount-latest-subvol b/filesystem/usr/local/bin/mount-latest-subvol index 3757814..005b693 100755 --- a/filesystem/usr/local/bin/mount-latest-subvol +++ b/filesystem/usr/local/bin/mount-latest-subvol @@ -152,7 +152,8 @@ get-btrfs-root-mountpoint() { mapper-dev devx fi d devx=$devx - root_dir=$(sed -rn "s,^\s*$devx\s+(\S+).*\bsubvolid=[05]\b.*,\1,p" /etc/mtab /etc/fstab|head -n1) + # note: we could also test for "subvol=/", but no need. + root_dir=$(awk '$1 == "'"$devx"'" && $3 == "btrfs" && ( $4 !~ /subvol=/ || $4 ~ /subvolid=[05](,|$)/ ) {print $2}' /etc/mtab /etc/fstab|head -n1) if [[ $root_dir ]]; then d root_dir=$root_dir break diff --git a/filesystem/usr/local/bin/prof-tail b/filesystem/usr/local/bin/prof-tail index f3df297..0529fdd 100755 --- a/filesystem/usr/local/bin/prof-tail +++ b/filesystem/usr/local/bin/prof-tail @@ -122,10 +122,12 @@ notify-cmd() { if [[ $line ]] && ! i3-check-profanity &>/dev/null; then dunstify -h string:x-dunst-stack-tag:profanity -- "$line" fi + sleep 1 } pre="^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}-[0-9]{2} -" +declare -i ret while true; do midnight=$(date -d '00:00:00 tomorrow' +%s) log_today=$(date '+%Y_%m_%d' "${dev_date[@]}").log @@ -137,9 +139,15 @@ while true; do tail-cmd | while true; do if (( EPOCHSECONDS > midnight + 3 )); then break; fi - read -t 15 -r l 2>/dev/null || continue + ret=0; read -t 15 -r l 2>/dev/null || ret=$? + # eg false|read + if (( ret == 1 )); then break; fi + # timeout + if (( ret == 142 )); then + continue + fi notify-cmd "$l" - done + done ||: sleep 2 done diff --git a/filesystem/usr/local/bin/rootsshsync b/filesystem/usr/local/bin/rootsshsync index 887fbb5..2cc0b34 100755 --- a/filesystem/usr/local/bin/rootsshsync +++ b/filesystem/usr/local/bin/rootsshsync @@ -88,6 +88,7 @@ if [[ -e /etc/systemd/system/ssh-agent-root.service ]]; then systemctl enable --now ssh-agent-root fi +if [[ -d /usr/share/doc/dropbear-initramfs ]]; then # note: i previously had $auth_dir/root/.ssh/authorized_keys # but /usr/share/doc/dropbear-initramfs/README.initramfs @@ -104,6 +105,7 @@ if [[ ! -e $auth_file ]] || ! diff -q /root/.ssh/authorized_keys $auth_file; the cp -p /root/.ssh/authorized_keys $auth_file update-initramfs -u -k all fi +fi if [[ -e /p/c/subdir_files/.dsh ]]; then rsync -tpur /p/c/subdir_files/.dsh /root diff --git a/filesystem/usr/local/bin/switch-mail-host b/filesystem/usr/local/bin/switch-mail-host index 809b4f5..e9d6d63 100755 --- a/filesystem/usr/local/bin/switch-mail-host +++ b/filesystem/usr/local/bin/switch-mail-host @@ -371,7 +371,7 @@ if (( ret )); then e finished restoring old host as primary, now exiting $ret due to earlier failed btrbk of /o. exit $ret fi -_s=$(stty size); c=${_s#* }; while ((c-- >0)); do printf $; done; echo +echo '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$' # new system is usable at this point # once I accidentally accepted incoming mail on old host. I used this script to copy over that mail: diff --git a/fsf-script-lib b/fsf-script-lib index d561fc6..cea16f7 100644 --- a/fsf-script-lib +++ b/fsf-script-lib @@ -1,10 +1,5 @@ #!/bin/bash -# Copyright (C) 2023 Free Software Foundation -# -# Note: the FSF recommends copyleft licensing for programs > 300 lines, see -# https://www.gnu.org/licenses/license-recommendations.en.html. -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -27,11 +22,15 @@ # block. set -e if [[ -s /usr/local/lib/bash-bear ]]; then + # shellcheck disable=SC1091 . /usr/local/lib/bash-bear elif [[ -s /usr/local/lib/err ]]; then # old name # shellcheck disable=SC1091 . /usr/local/lib/err +elif [[ -s ${BASH_SOURCE[0]%/*}/bash-bear ]]; then + # shellcheck disable=SC1091 # checking script dir. + . ${BASH_SOURCE[0]%/*}/bash-bear elif [[ $- != *i* ]]; then # error if this is a script, not an interactive shell. echo "error: exit 1: missing dependency: /usr/local/lib/bash-bear" @@ -183,6 +182,13 @@ mq() { # echo MESSAGE, but use printf so it is safe from options. e() { printf "%s\n" "$*"; } +# echo but only when verbose is true. +ev() { + if [[ $verbose == true ]]; then + e "$@" + fi +} + # usage: ml COMMAND... # # Write successful command to log. @@ -254,158 +260,12 @@ dr() { # 2025-01-03 03:51:59 main: test message2 err() { echo "$(date "+%F %T") ${FUNCNAME[1]}: $*" >&2; } -### begin debug-setx related functions ### -# -# usage: debug-setx -# -# Print executing commands like "set -x", but: -# -# - Skips printing many boring/redundant lines. There are related -# functions below to modify/toggle what gets printed. -# -# - Related function h() to prompt before executing printed command. -# -# Printing of uninteresting commands can be limited: -# -# 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). -# -# There is a hard-coded list of commands to skip or maybe skip. You can -# improve this. -# -debug-setx() { - local existing_debug_trap - - # Note on commands we skip printing: - # - read ends up being what is shown for 'while read' loops. - - # for inheriting debug in subshells - shopt -s extdebug - - debug_prompt=false - debug_skip=false - debug_force_print=false - - existing_debug_trap=$(trap -p DEBUG 2>&1) - if [[ $existing_debug_trap && $existing_debug_trap != *_debug-setx-func ]]; then - trap "$existing_debug_trap; _debug-setx-func" DEBUG - else - trap _debug-setx-func DEBUG - fi +# Do the equivalent of head on file that might not have line breaks or +# might be gobblygook. The sed fixes any missing final newline. +peek() { + cat -Ans -- "$1" | head -n20 | head -c1500 | sed a\\ || [[ $? == 141 ]] } -# internal function called via debug-setx trap. -_debug-setx-func() { - local doprint=false random_delimiter func cmd col debug_cmd - if [[ $debug_max_stack_depth ]]; then - 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=99999 - fi - - if [[ $BASH_SUBSHELL != [01] ]]; then - return 0 - fi - - if $debug_skip; then - debug_skip=false - return 0 - fi - - if $debug_prompt; then - doprint=true - fi - - if $debug_force_print; then - debug_force_print=false - doprint=true - fi - - if $debug_print_default; then - - ## block for debug_print_funcs - if ! $doprint; then - for func in ${debug_print_funcs[@]}; do - if [[ $func == "${FUNCNAME[1}" ]]; then - doprint=true - break - fi - done - fi - - ## block for default command & function ignoring - if ! $doprint && (( ${#FUNCNAME[*]} <= funcname_count_max )); then - # debug - #e "${FUNCNAME[*]} ${#FUNCNAME[*]} <= $funcname_count_max" - case $BASH_COMMAND in - e\ *|err\ *|echo\ *|printf\ *|read\ *|h|ux|ux\ *) - : ;; - for\ *) - # try to print just the first for loop iteration. - _debug_setx_cur_for="$BASH_COMMAND ${BASH_LINENO[0]} ${FUNCNAME[1]}" - if [[ $_debug_setx_cur_for != "$_debug_setx_last_for" ]]; then - doprint=true - fi - _debug_setx_last_for="$_debug_setx_cur_for" - ;; - *) - doprint=true - ;; - esac - fi - - fi - - if $doprint; then - # Expanding $1 will be empty, so skip expansion in that case, and some others. - # - # TODO: we should be able to grab $1 from the function tracing facilities. - # - # Note, we could split the command up and expand other parts - # but I'm not going to bother. - if [[ $BASH_COMMAND != *\$[0-9]* && $BASH_COMMAND != *\`* && $BASH_COMMAND != *\$\(* && $BASH_COMMAND == *\$* ]]; then - random_delimiter=$RANDOM$RANDOM$RANDOM - # shellcheck disable=SC1003 - _d="$BASH_COMMAND" _d="${_d//'\\'/SUBfopguensOfRifejmu${random_delimiter}SUB}" _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//SUBfopguensOfRifejmu${random_delimiter}SUB/'\\\\'}" - cmd="${_d@P}" - else - cmd="$BASH_COMMAND" - fi - [[ $COLUMNS ]] || { _s=$(stty size); COLUMNS=${_s#* }; } - if [[ $COLUMNS == *[0-9]* ]]; then - # generally fill up 2 rows - col=$(( COLUMNS * 2 - 20 )) - else - col=150 - fi - if (( ${#cmd} > col )); then - cmd="$(( ${#cmd} - col)) cut: ${cmd:0:col}" - fi - echo "+ $cmd" >&2 - fi - - if $debug_prompt; then - # we can type in commands here to inspect the program state. - read -r -e -p "DEBUG $ " debug_cmd - while [[ $debug_cmd ]]; do - eval $debug_cmd - read -r -e -p "DEBUG $ " debug_cmd - done - debug_prompt=false - fi -} - -# usage: ux [COMMAND...] -# -# disable/unset debug-setx default command printing. Runs COMMAND if -# given. Command arg exists only because the args would be otherwise -# unused. -ux() { - debug_print_default=false - if [[ $1 ]]; then "$@"; fi -} # usage: h [COMMAND...] # @@ -414,11 +274,10 @@ ux() { # # note: h = random free letter. h() { + # shellcheck disable=SC2034 + debug_prompt=true if [[ $1 ]]; then - debug_prompt=true "$@" - else - debug_prompt=true fi } @@ -428,153 +287,3 @@ die() { exit 1 } -# usage: u1 [COMMAND...] -# -# Disable debug-setx printing just for the next command. -u1() { - # we have this strange logic because [[ is a command, easier to not - # have that be between debug_skip=true and $@ and trigger a debug - # trap. - if [[ $1 ]]; then - debug_skip=true - "$@" - else - debug_skip=true - fi -} - -# usage: dx [COMMAND...] -# -# Undo ux() and reenable debug-setx printing. -dx() { - if [[ $1 ]]; then - debug_print_default=true - "$@" - else - debug_print_default=true - fi -} - -# usage: d1 [COMMAND...] -# -# For just one command, reenable debug-setx printing. -d1() { - if [[ $1 ]]; then - debug_force_print=true - "$@" - else - debug_force_print=true - fi -} - - -# usage: setx-func [FUNCTION...] -# -# Do debug-setx printing within current function or FUNCTION(s) even -# when called with function stack size greater than -# $debug_max_stack_depth. -setx-func() { - local new_func new_funcs found existing_func - if [[ ! -v debug_print_funcs ]]; then - debug_print_funcs=() - fi - - e "${FUNCNAME[*]}" - if [[ $1 ]]; then - new_funcs="$*" - else - new_funcs="${FUNCNAME[0]}" - fi - for new_func in $new_funcs; do - found=false - for existing_func in ${debug_print_funcs[@]}; do - if [[ $existing_func == "$new_func" ]]; then - found=true - break - fi - done - if $found; then - break - fi - debug_print_funcs+=($new_func) - done -} - -### 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-lib.sh b/g-lib.sh index 54acd6b..7bbf8d1 100755 --- a/g-lib.sh +++ b/g-lib.sh @@ -38,7 +38,7 @@ g() { fi if [[ $server == none ]]; then - server= + server=server else args+=" -s$server" fi diff --git a/i3-sway/bar.conf b/i3-sway/bar.conf index 192b185..4244a3a 100644 --- a/i3-sway/bar.conf +++ b/i3-sway/bar.conf @@ -1,24 +1,16 @@ -# by default, new workspaces are created on whatever screen doesn't have -# one active or else the current one. That is annoying, I have one -# primary monitor, I don't want a new workspace created on secondary -# monitor just because I happen be focused on it. This fixes that. -workspace 1 output primary -workspace 2 output MON-LEFT -workspace 3 output MON-RIGHT -workspace 4 output MON-RIGHT -workspace 5 output MON-RIGHT -workspace 6 output MON-RIGHT -workspace 7 output MON-RIGHT -workspace 8 output MON-RIGHT -workspace 9 output MON-RIGHT -workspace 10 output MON-RIGHT + # todo: this is probably preferable on an x200. Makes the default layout be splitv instead of splith. #default_orientation vertical + # bar is needed for kde connect bar { +# conditionally set in myx +#mode hide +#hidden_state hide + # keep it only on secondary monitor to save space and make for less # missing pixes in obs live stream. For docs on this, search "output # primary" in the i3 guide. diff --git a/i3-sway/common.conf b/i3-sway/common.conf index f8bdc7b..7f5245b 100644 --- a/i3-sway/common.conf +++ b/i3-sway/common.conf @@ -65,6 +65,9 @@ bindsym $mod+r $ex "/a/bin/ds/xl" bindsym $mod+backslash $ex "scrot" bindsym $mod+t $ex "i3-set-layout splitv" +## but this is set dynamically by myx +bindsym $mod+Shift+t "move workspace to output next" + bindsym $mod+g $ex "i3-set-layout tabbed" @@ -154,6 +157,23 @@ bindsym $mod+8 workspace 9 bindsym $mod+Shift+9 move container to workspace 10 bindsym $mod+9 workspace 10 +# by default, new workspaces are created on whatever screen doesn't have +# one active or else the current one. That is annoying, I have one +# primary monitor, I don't want a new workspace created on secondary +# monitor just because I happen be focused on it. This fixes that. + +workspace 1 output primary +workspace 2 output primary +workspace 3 output primary +workspace 4 output primary +workspace 5 output primary +workspace 6 output primary +workspace 7 output primary +workspace 8 output primary +workspace 9 output primary +workspace 10 output primary + + bindsym $mod+m $ex "dunstctl close-all" bindsym $mod+Shift+m border toggle @@ -229,4 +249,3 @@ for_window [class="focus" instance="focus"] floating disable client.focused #4c7899 #285577 #ffffff #2e9ef4 #ff4400 client.focused_inactive #333333 #5f676a #ffffff #484e50 #B8C8CD client.unfocused #333333 #222222 #888888 #292d2e #B8C8CD - diff --git a/icc-load b/icc-load index 4c72051..f985923 100755 --- a/icc-load +++ b/icc-load @@ -55,13 +55,29 @@ # https://wiki.archlinux.org/title/ICC_profiles said it was less # compatible, so I didn't bother. + +# I got a viewsonic and found its color to be noticably different +# than the dell, so recalibrated. However, I've realized that to +# generate a better icc profile, I should extract some data from the +# windows software to calibrate my specific device, and to compare +# the icc profile it generates with displaycal, and to read the +# displaycal manual and test some things. Until then, I'm happy to +# just rely on osd settings that make the monitors look good and +# similar in a test video showing lots of skin tones. + + +exit 0 + case $HOSTNAME in frodo) - /usr/bin/dispwin -v -d1 -c -I '/a/bin/ds/icc/U3225QE #1 2025-07-29 01-57 D6500 2.2 F-S XYZLUT+MTX.icc' + +# /usr/bin/dispwin -v -d1 -c -I '/a/bin/ds/icc/U3225QE #1 2025-07-29 01-57 D6500 2.2 F-S XYZLUT+MTX.icc' +# /usr/bin/dispwin -v -d1 -c -I '/a/bin/ds/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc' # test that it worked with: # dispwin -v -d1 -V '/etc/xdgcolor/icc/devices/display/U3225QE #1 2025-07-29 01-57 D6500 2.2 F-S XYZLUT+MTX.icc' # # You can also watch the grey color of konsole change slightly when it loads. + /usr/bin/dispwin -v -d3 -c -I '/a/bin/ds/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc' ;; esac diff --git a/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc b/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc new file mode 100644 index 0000000..cab888f Binary files /dev/null and b/icc/U3225QE #1 2026-09-24 03-06 D6500 S XYZLUT+MTX.icc differ diff --git a/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc b/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc new file mode 100644 index 0000000..a6a32c8 Binary files /dev/null and b/icc/VP2488-4K #1 2026-09-24 01-14 D6500 2.2 F-S XYZLUT+MTX.icc differ diff --git a/machine_specific/frodo/filesystem/etc/default/isc-dhcp-server b/machine_specific/frodo/filesystem/etc/default/isc-dhcp-server new file mode 100644 index 0000000..b8dd017 --- /dev/null +++ b/machine_specific/frodo/filesystem/etc/default/isc-dhcp-server @@ -0,0 +1,18 @@ +# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server) + +# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf). +#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf +#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf + +# Path to dhcpd's PID file (default: /var/run/dhcpd.pid). +#DHCPDv4_PID=/var/run/dhcpd.pid +#DHCPDv6_PID=/var/run/dhcpd6.pid + +# Additional options to start dhcpd with. +# Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead +#OPTIONS="" + +# On what interfaces should the DHCP server (dhcpd) serve DHCP requests? +# Separate multiple interfaces with spaces, e.g. "eth0 eth1". +INTERFACESv4="eth0" +INTERFACESv6="" diff --git a/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf-orig b/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf-orig new file mode 100644 index 0000000..138993d --- /dev/null +++ b/machine_specific/frodo/filesystem/etc/dhcp/dhcpd.conf-orig @@ -0,0 +1,111 @@ +# dhcpd.conf +# +# Sample configuration file for ISC dhcpd +# +# Attention: If /etc/ltsp/dhcpd.conf exists, that will be used as +# configuration file instead of this file. +# + +# option definitions common to all supported networks... +option domain-name "example.org"; +option domain-name-servers ns1.example.org, ns2.example.org; + +default-lease-time 600; +max-lease-time 7200; + +# The ddns-updates-style parameter controls whether or not the server will +# attempt to do a DNS update when a lease is confirmed. We default to the +# behavior of the version 2 packages ('none', since DHCP v2 didn't +# have support for DDNS.) +ddns-update-style none; + +# If this DHCP server is the official DHCP server for the local +# network, the authoritative directive should be uncommented. +#authoritative; + +# Use this to send dhcp log messages to a different log file (you also +# have to hack syslog.conf to complete the redirection). +#log-facility local7; + +# No service will be given on this subnet, but declaring it helps the +# DHCP server to understand the network topology. + +#subnet 10.152.187.0 netmask 255.255.255.0 { +#} + +# This is a very basic subnet declaration. + +#subnet 10.254.239.0 netmask 255.255.255.224 { +# range 10.254.239.10 10.254.239.20; +# option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org; +#} + +# This declaration allows BOOTP clients to get dynamic addresses, +# which we don't really recommend. + +#subnet 10.254.239.32 netmask 255.255.255.224 { +# range dynamic-bootp 10.254.239.40 10.254.239.60; +# option broadcast-address 10.254.239.31; +# option routers rtr-239-32-1.example.org; +#} + +# A slightly different configuration for an internal subnet. +#subnet 10.5.5.0 netmask 255.255.255.224 { +# range 10.5.5.26 10.5.5.30; +# option domain-name-servers ns1.internal.example.org; +# option domain-name "internal.example.org"; +# option subnet-mask 255.255.255.224; +# option routers 10.5.5.1; +# option broadcast-address 10.5.5.31; +# default-lease-time 600; +# max-lease-time 7200; +#} + +# Hosts which require special configuration options can be listed in +# host statements. If no address is specified, the address will be +# allocated dynamically (if possible), but the host-specific information +# will still come from the host declaration. + +#host passacaglia { +# hardware ethernet 0:0:c0:5d:bd:95; +# filename "vmunix.passacaglia"; +# server-name "toccata.example.com"; +#} + +# Fixed IP addresses can also be specified for hosts. These addresses +# should not also be listed as being available for dynamic assignment. +# Hosts for which fixed IP addresses have been specified can boot using +# BOOTP or DHCP. Hosts for which no fixed address is specified can only +# be booted with DHCP, unless there is an address range on the subnet +# to which a BOOTP client is connected which has the dynamic-bootp flag +# set. +#host fantasia { +# hardware ethernet 08:00:07:26:c0:a5; +# fixed-address fantasia.example.com; +#} + +# You can declare a class of clients and then do address allocation +# based on that. The example below shows a case where all clients +# in a certain class get addresses on the 10.17.224/24 subnet, and all +# other clients get addresses on the 10.0.29/24 subnet. + +#class "foo" { +# match if substring (option vendor-class-identifier, 0, 4) = "SUNW"; +#} + +#shared-network 224-29 { +# subnet 10.17.224.0 netmask 255.255.255.0 { +# option routers rtr-224.example.org; +# } +# subnet 10.0.29.0 netmask 255.255.255.0 { +# option routers rtr-29.example.org; +# } +# pool { +# allow members of "foo"; +# range 10.17.224.10 10.17.224.250; +# } +# pool { +# deny members of "foo"; +# range 10.0.29.10 10.0.29.230; +# } +#} diff --git a/machine_specific/frodo/filesystem/etc/network/interfaces.d/eth10g b/machine_specific/frodo/filesystem/etc/network/interfaces.d/eth10g deleted file mode 100644 index 3770183..0000000 --- a/machine_specific/frodo/filesystem/etc/network/interfaces.d/eth10g +++ /dev/null @@ -1,41 +0,0 @@ -## example of 2 independent networks: - -# # top port -# auto eth2 -# iface eth2 inet static -# address 10.3.0.4/24 - -# # bottom port -# auto eth1 -# iface eth1 inet static -# address 10.9.0.4/24 - - -## manual bond configuration example: -# modprobe bonding -# echo +bond0 > /sys/class/net/bonding_masters -# echo +eth2 > /sys/class/net/bond0/bonding/slaves -# echo +eth1 > /sys/class/net/bond0/bonding/slaves -# ip addr add 10.3.0.4/24 dev bond0 -# ip link set bond0 up - -## things not needed for us, but could be useful elsewhere: - -# Set MII monitoring interval to 100ms for link detection -#echo 100 > /sys/class/net/bond0/bonding/miimon - -## bonding mode (we happen to be using the default) -#ip link set bond0 down -#echo balance-rr > /sys/class/net/bond0/bonding/mode - -# Also, set slaves to down before adding them. - -# status lookup: -# cat /proc/net/bonding/bond0 -# cat /sys/class/net/bond0/bonding/slaves -# cat /sys/class/net/bonding_masters - - -auto eth1 -iface eth1 inet static -address 10.3.0.4/24 diff --git a/machine_specific/frodo/filesystem/etc/systemd/system/frodo-route.service b/machine_specific/frodo/filesystem/etc/systemd/system/frodo-route.service new file mode 100644 index 0000000..804ebb5 --- /dev/null +++ b/machine_specific/frodo/filesystem/etc/systemd/system/frodo-route.service @@ -0,0 +1,13 @@ +[Unit] +Description=Setup of frodo routing rules +After=network.target +Wants=network.target +StartLimitIntervalSec=0 + +[Service] +Type=oneshot +RemainAfterExit=true +ExecStart=/usr/local/bin/frodo-route + +[Install] +WantedBy=multi-user.target diff --git a/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr-pre@.service b/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr-pre@.service index 1e6017e..128c86c 100644 --- a/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr-pre@.service +++ b/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr-pre@.service @@ -3,7 +3,7 @@ Description=Initial setup of netns for wg-quick-tr %I [Service] Type=oneshot -ExecStart=/usr/bin/flock -w 20 /tmp/newns.flock /usr/local/bin/newns -n 10.174.34 start %i +ExecStart=/usr/bin/flock -w 20 /tmp/newns.flock /usr/local/bin/newns -n 10.174.1 start %i ExecStop=/usr/bin/flock -w 20 /tmp/newns.flock /usr/local/bin/newns stop %i RemainAfterExit=yes diff --git a/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr@.service b/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr@.service index 2afc643..b2ef48a 100644 --- a/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr@.service +++ b/machine_specific/frodo/filesystem/etc/systemd/system/wg-quick-tr@.service @@ -9,11 +9,11 @@ Documentation=man:wg(8) Type=simple ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip %i)' ExecStartPre=/sbin/iptables-restore /a/bin/distro-setup/transmission-firewall/netns.rules -ExecStartPre=/usr/sbin/ip r add 10.8.0.0/24 via 10.174.34.1 dev veth1-client +ExecStartPre=/usr/sbin/ip r add 10.8.0.0/24 via 10.174.1.1 dev veth1-client ExecStartPre=/usr/bin/wg-quick up %i ExecStart=/bin/sleep infinity ExecStopPost=/usr/bin/wg-quick down %i -ExecStopPost=/usr/sbin/ip r del 10.8.0.0/24 via 10.174.34.1 dev veth1-client +ExecStopPost=/usr/sbin/ip r del 10.8.0.0/24 via 10.174.1.1 dev veth1-client NetworkNamespacePath=/var/run/netns/%i BindReadOnlyPaths=/etc/tr-resolv:/run/systemd/resolve:norbind /etc/basic-nsswitch:/etc/resolved-nsswitch:norbind # copied from wg-quick@.service diff --git a/machine_specific/kd/filesystem/etc/network/interfaces.d/eth10g b/machine_specific/kd/filesystem/etc/network/interfaces.d/eth10g deleted file mode 100644 index 50d8bb4..0000000 --- a/machine_specific/kd/filesystem/etc/network/interfaces.d/eth10g +++ /dev/null @@ -1,19 +0,0 @@ - -## example of 2 independent networks: - -# # top right port -# auto eth0 -# iface eth0 inet static -# address 10.3.0.2/24 - -# # bottom left port -# auto eth2 -# iface eth2 inet static -# address 10.9.0.2/24 -# # - - -auto eth0 -iface eth0 inet static -address 10.3.0.2/24 -# diff --git a/machine_specific/li/filesystem/etc/openvpn/client-config-hole/frodo b/machine_specific/li/filesystem/etc/openvpn/client-config-hole/frodo index 7fbb17c..de17a56 100644 --- a/machine_specific/li/filesystem/etc/openvpn/client-config-hole/frodo +++ b/machine_specific/li/filesystem/etc/openvpn/client-config-hole/frodo @@ -1 +1 @@ -ifconfig-push 10.5.5.34 255.255.255.0 +ifconfig-push 10.5.5.1 255.255.255.0 diff --git a/mail-setup b/mail-setup index 971ec5c..d4987ff 100755 --- a/mail-setup +++ b/mail-setup @@ -19,10 +19,15 @@ # SPDX-License-Identifier: GPL-3.0-or-later -# TODO: track the actual generated exim config files in git. Somehow an -# exim update screwed up the config file, probably by generating it -# outside of the normal processes. It was fixed when I reran this file, -# but then I didn't actually know for sure what went wrong. +# TODO: on desktop, somehow +# exim updates screwed up the config file, probably by generating it +# outside of the normal processes. I'm tracking those changes via +# copies to +# /etc/etckeeper/fsmirror/var/lib/exim4/config.autogenerated +# which is done via the script: +# /a/c/filesystem/etc/etckeeper/commit.d/20iank-mirror. use that +# to figure out a solution +# # todo: # on bk (and fsf servers that run multiple exim4 daemons, eg eximfsf2 and eximfsf3), @@ -412,9 +417,12 @@ son() { for service; do enabled=$(systemctl is-enabled $service 2>/dev/null ||:) if [[ $enabled != enabled ]]; then - m systemctl enable $service + m systemctl --now enable $service + continue + fi + if ! systemctl --quiet is-active $service; then + m systemctl start $service fi - m systemctl start $service done } mailhost() { @@ -510,14 +518,6 @@ use_rspamd=false # installs epanicclean iptables-exim ip6tables-exim /a/bin/ds/install-my-scripts -if [[ $(debian-codename-compat) == bionic ]]; then - cat >/etc/apt/preferences.d/spamassassin <<'EOF' -Package: spamassassin sa-compile spamc -Pin: release n=focal,o=Ubuntu -Pin-Priority: 500 -EOF -fi - unit-exists() { systemctl cat $1 &>/dev/null @@ -572,26 +572,6 @@ esac # bad packages that sometimes get automatically installed pu openresolv resolvconf -soff openvpn - - -if [[ $(debian-codename) == etiona ]]; then - # ip6tables stopped loading on boot. openvpn has reduced capability set, - # so running iptables as part of openvpn startup wont work. This should do it. - pi iptables-persistent - cat >/etc/iptables/rules.v6 <<'EOF' -*mangle -COMMIT -*nat -COMMIT -EOF - # load it now. - m ip6tables -S >/dev/null -fi - -# our nostart pi fails to avoid enabling - - # * initial dns config & daemon setup # @@ -699,9 +679,12 @@ EOF # old file. remove when all hosts updated, 2023-09-11 rm -fv /etc/exim4/conf.d/clamav_data_acl +if ! groups clamav | grep -q Debian-exim; then + m usermod -a -G Debian-exim clamav +fi + pi-nostart clamav -m usermod -a -G Debian-exim clamav u /etc/systemd/system/clamav-daemon.service.d/fix.conf <>/etc/cron.d/mailtest <$xf m() { if $dry_run; then @@ -93,108 +72,12 @@ m() { fi } - - -primary_info=$(awk '$2 == "connected" && $3 == "primary" {print $1,$4}' $xf) - -secondary_out=$(awk '$2 == "connected" && $3 != "primary" {print $1}' $xf) -# Some systems only have a non-primary connected. -if [[ ! $primary_info ]]; then - primary_info=$(awk '$2 == "connected" {print $1,$3}' $xf) - xrandr --output $secondary_out --primary - secondary_out= -fi - -# res_info eg: 3840x2160+1920+0 -read -r primary_out primary_res_info <<<"$primary_info" - -primary_res=${primary_res_info%%+*} -primary_x=${primary_res%x*} -primary_y=${primary_res#*x} - -if [[ $secondary_out ]]; then - - x_offset=$primary_x - left_right_arg=--right-of - - # dp-1 moves from left to right sometimes, i just move it out of the - # conditional and comment it as needed. - - winchair=false - if edid-test 192efbdcef; then - winchair=true - fi - - if $winchair; then - left_right_arg=--left-of - x_offset=0 - fi - - - # its a small monitor, so I run: - # startx -- -dpi 120 - # - # And x decides the primary display should have non-full - # resolution. This is a quick hopefully temporary fix. - if $winchair; then - xrandr --output eDP-1 --mode 1920x1200 - fi - - - left_right_arg="$left_right_arg $primary_out" - - target_out=$secondary_out - target_res=$(grep -A1 -E "^$secondary_out " $xf | tail -n1 | awk '{print $1}') - target_x=${target_res%x*} - target_y=${target_res#*x} -else - target_out=$primary_out - x_offset=0 - target_res=$primary_res - target_x=$primary_x - target_y=$primary_y -fi - - -if (( target_x <= 1280 )); then - quarter=false - tall=false -elif (( target_x <= 1920 )); then - quarter=false - tall=true -fi - - ##### begin command line parsing ######## -temp=$(getopt -l help fnrs: "$@") || usage 1 +temp=$(getopt -l help h "$@") || usage 1 eval set -- "$temp" while true; do case $1 in - -f) - downres=false - quarter=false - tall=false - ;; - -n) dry_run=true ;; - -s) - case $2 in - tall) - tall=true - quarter=false - ;; - quarter) - tall=false - quarter=true - ;; - full) - tall=false - quarter=false - ;; - esac - shift - ;; - -r) restart=true ;; -h|--help) usage 0 ;; --) shift; break ;; *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;; @@ -205,136 +88,29 @@ done ##### end command line parsing ######## -if $downres && (( target_x > 2560 )); then - target_x=2560 - target_y=1440 - target_res=${target_x}x$target_y +if [[ $HOSTNAME == frodo ]]; then + # saved arandr command + xrandr --output HDMI-0 --mode 3840x2160 --pos 11520x0 --rotate normal --output DP-0 --primary --mode 3840x2160 --pos 0x0 --rotate normal --output DP-1 --off --output DP-2 --mode 3840x2160 --pos 3840x0 --rotate normal --output DP-3 --off --output DP-4 --mode 3840x2160 --pos 7680x0 --rotate normal --output DP-5 --off fi -half_x=$(( target_x / 2 )) -half_y=$(( target_y / 2 )) - - -for mon_suffix in TOP-LEFT BOTTOM-LEFT LEFT RIGHT; do - if xrandr --listmonitors | awk '$2 == "MON-'$mon_suffix\" |grep . >/dev/null; then - m xmod --delmonitor MON-$mon_suffix - fi -done - -if [[ ! $secondary_out ]] || grep -A1 disconnected $xf | grep '^[[:space:]]'; then - # gets rid of leftover secondary - if [[ $HOSTNAME != frodo ]]; then - m xmod --auto - - # new monitor on frodo, I've been having to run this to get the full refresh rate: - # xrandr --output DP-0 --mode 3840x2160 --rate 120 - # testing if this xmod is getting in the way. - fi -fi - -if [[ $secondary_out ]] && $restart; then - m xmod --output $secondary_out --off - m sleep 2 -fi - -if [[ $secondary_out || $primary_res != "$target_res" ]]; then - m xmod --output $target_out $left_right_arg --mode $target_res -fi - -if $tall; then - # 298 & 336 are millimeters. I took them from a monitor I was using. I - # don't know if they are important, I assume not important enough to - # change for different monitors. - m xmod --setmonitor MON-LEFT $half_x/298x$target_y/336+$x_offset+0 $target_out - m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none - -elif $quarter; then - m xmod --setmonitor MON-LEFT $half_x/298x$half_y/336+$x_offset+0 $target_out - # note: this bottom left is buggy when it comes to context menus, - # including in web pages. In the tall configuration, I sometimes see - # them in another "monitor" area, but with this bottom left monitor, - # they aren't displayed at all, as if the window system is displaying - # them off screen. When that happens, I just switch to the tall - # configuration, use the dialog, and them maybe switch back. - m xmod --setmonitor MON-BOTTOM-LEFT $half_x/298x$half_y/336+$x_offset+$half_y none - m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none -fi - - -## begin i3 config ## -move_outputs=() -ws_outputs=() -if [[ $secondary_out ]]; then - ws1_output=$primary_out - move_outputs=($primary_out) -elif $tall || $quarter; then - ws1_output=MON-RIGHT -fi - -ws_outputs=( - $ws1_output -) - - -if $tall; then - ws_outputs+=( - MON-LEFT - MON-RIGHT - ) - move_outputs+=(MON-RIGHT) -elif $quarter; then - ws_outputs+=( - MON-LEFT - MON-BOTTOM-LEFT - MON-RIGHT - ) - move_outputs+=(MON-BOTTOM-LEFT MON-RIGHT) -elif [[ $secondary_out ]]; then - move_outputs+=($secondary_out) - ws_outputs+=($secondary_out) - -fi - -#echo d1 ${ws_outputs[@]} - -rm -f ~/i3-myx.conf -total_ws_count=11 -for (( i=0; i>~/i3-myx.conf -done - { cat /a/bin/ds/i3-sway/bar.conf - ## for when we are temporarily 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. + + ## I made this conditional once when running some automation which + ## auto-unhides the bar constantly and overlaps the bottom of windows + # #echo "}" - if [[ $secondary_out ]]; then - echo "}" - else echo 'mode hide hidden_state hide }' - fi } >> ~/i3-myx.conf -if (( ${#move_outputs[@]} )); then - echo "bindsym \$mod+Shift+t move workspace to output ${move_outputs[*]} # set by myx" >>~/i3-myx.conf -else - echo "# bindsym \$mod+Shift+t move workspace to output XXX XXX # note: if we had logical X screen or multimons, this would be set by myx" >>~/i3-myx.conf -fi # give it some time to reload or adjust to new x settings. +sleep 1 # i3-msg -t get_outputs | jq -C . # showed @@ -365,57 +141,8 @@ fi # This was incorrect. The correct thing is that DP-1 is active, HDMI-2 is not active. # Restarting i3 did not help. -sleep 1 -m /a/bin/ds/i3-sway/gen $gen_arg - -if (( ${#ws_outputs[@]} )); then - - declare -A ws_expected_out - - for (( i=0; i 20 )); then - cat <<'EOF' >&2 - -ERROR: moving workspaces is not working as expected I've seen it happen -that an output should not exist anymore. Restarting i3 fixed it, reloading did not. -This script did a restart, but it might need a sleep before doing so. -EOF - exit 1 - fi - refresh_count=$(( refresh_count + 1 )) - refresh_workspaces=false - tmps=$(i3 -t get_workspaces) - tmps=$(jq -r '.[] | .num, .output' <<<"$tmps") - while read -r ws; do - read -r output || break - if [[ $ws != [0-9] && $ws != 10 ]]; then - echo "$0: error: unexpected workspace found: $ws. continuing" - continue - fi - if [[ ${ws_expected_out[$ws]} != "$output" ]]; then - m i3 '[workspace="'$ws'"]' move workspace to output ${ws_expected_out[$ws]} - refresh_workspaces=true - break - fi - done <<<"$tmps" - done -fi +m /a/bin/ds/i3-sway/gen + ## end i3 config ## @@ -425,21 +152,3 @@ m /a/exe/input-setup echo -n "myx end: " date "+%A, %B %d, %r, %S seconds" - -# myx -f -# Tuesday, July 23, 05:54:37 PM, 37 seconds -# myx: xmod --delmonitor MON-LEFT -# myx: xmod --delmonitor MON-RIGHT -# myx: xmod --output DP-1 --right-of eDP-1 --mode 3840x2160 -# d1 eDP-1 DP-1 -# myx: /a/bin/ds/i3-sway/gen -r -# /a/bin/ds/i3-sway/gen: i3-msg restart -# [{"success":true}] -# myx: i3 [workspace="2"] move workspace to output DP-1 -# ERROR: No output matched -# [{"success":false,"error":"No output matched"}] -# /a/exe/myx:63: `i3-msg "$@"' returned 2 -# from /a/exe/myx:63:in `i3 [workspace="2"] move workspace to output DP-1' -# from /a/exe/myx:88:in `m i3 [workspace="2"] move workspace to output DP-1' -# from /a/exe/myx:330:in `main -f' -# /a/exe/myx: exiting with status 2 diff --git a/myx-old b/myx-old new file mode 100755 index 0000000..64ad5b5 --- /dev/null +++ b/myx-old @@ -0,0 +1,439 @@ +#!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to change +# to a recommended GPL license. + +# Copyright 2024 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e; . /usr/local/lib/bash-bear; set +e + +script_name="${0##*/}" +usage() { + cat </dev/null || [[ $? == 141 ]] +} + +i3() { + if [[ $I3SOCK ]]; then + i3-msg "$@" + fi +} +xmod() { + xrandr "$@" + gen_arg=-r +} + +date "+%A, %B %d, %r, %S seconds" + + +dry_run=false +downres=false +quarter=false +tall=false +restart=false + + +xf=$(mktemp) +xrandr >$xf + +m() { + if $dry_run; then + printf "$script_name: dry run: %s\n" "$*" + else + printf "$script_name: %s\n" "$*"; "$@" + fi +} + + + +primary_info=$(awk '$2 == "connected" && $3 == "primary" {print $1,$4}' $xf) + +secondary_out=$(awk '$2 == "connected" && $3 != "primary" {print $1}' $xf) +# Some systems only have a non-primary connected. +if [[ ! $primary_info ]]; then + primary_info=$(awk '$2 == "connected" {print $1,$3}' $xf) + xrandr --output $secondary_out --primary + secondary_out= +fi + +# res_info eg: 3840x2160+1920+0 +read -r primary_out primary_res_info <<<"$primary_info" + +primary_res=${primary_res_info%%+*} +primary_x=${primary_res%x*} +primary_y=${primary_res#*x} + +if [[ $secondary_out ]]; then + + x_offset=$primary_x + left_right_arg=--right-of + + left_right_arg="$left_right_arg $primary_out" + + target_out=$secondary_out + target_res=$(grep -A1 -E "^$secondary_out " $xf | tail -n1 | awk '{print $1}') + target_x=${target_res%x*} + target_y=${target_res#*x} +else + target_out=$primary_out + x_offset=0 + target_res=$primary_res + target_x=$primary_x + target_y=$primary_y +fi + +tall=false +quarter=false +downres=false + + +##### begin command line parsing ######## + +temp=$(getopt -l help fnrs: "$@") || usage 1 +eval set -- "$temp" +while true; do + case $1 in + -f) + downres=false + quarter=false + tall=false + ;; + -n) dry_run=true ;; + -s) + case $2 in + auto) + if (( target_x <= 1280 )); then + quarter=false + tall=false + elif (( target_x <= 1920 )); then + quarter=false + tall=true + fi + ;; + tall) + tall=true + quarter=false + ;; + quarter) + tall=false + quarter=true + ;; + full) + tall=false + quarter=false + ;; + esac + shift + ;; + -r) restart=true ;; + -h|--help) usage 0 ;; + --) shift; break ;; + *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;; + esac + shift +done + +##### end command line parsing ######## + + +if $downres && (( target_x > 2560 )); then + target_x=2560 + target_y=1440 + target_res=${target_x}x$target_y +fi + + +half_x=$(( target_x / 2 )) +half_y=$(( target_y / 2 )) + + +for mon_suffix in TOP-LEFT BOTTOM-LEFT LEFT RIGHT; do + if xrandr --listmonitors | awk '$2 == "MON-'$mon_suffix\" |grep . >/dev/null; then + m xmod --delmonitor MON-$mon_suffix + fi +done + +if [[ ! $secondary_out ]] || grep -A1 disconnected $xf | grep '^[[:space:]]'; then + # gets rid of leftover secondary + if [[ $HOSTNAME != frodo ]]; then + m xmod --auto + + # new monitor on frodo, I've been having to run this to get the full refresh rate: + # xrandr --output DP-0 --mode 3840x2160 --rate 120 + # testing if this xmod is getting in the way. + fi +fi + +if [[ $secondary_out ]] && $restart; then + m xmod --output $secondary_out --off + m sleep 2 +fi + +if [[ $secondary_out || $primary_res != "$target_res" ]]; then + : # todo: update this based on current monitor setup. + #m xmod --output $target_out $left_right_arg --mode $target_res +fi + +if $tall; then + # 298 & 336 are millimeters. I took them from a monitor I was using. I + # don't know if they are important, I assume not important enough to + # change for different monitors. + m xmod --setmonitor MON-LEFT $half_x/298x$target_y/336+$x_offset+0 $target_out + m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none + +elif $quarter; then + m xmod --setmonitor MON-LEFT $half_x/298x$half_y/336+$x_offset+0 $target_out + # note: this bottom left is buggy when it comes to context menus, + # including in web pages. In the tall configuration, I sometimes see + # them in another "monitor" area, but with this bottom left monitor, + # they aren't displayed at all, as if the window system is displaying + # them off screen. When that happens, I just switch to the tall + # configuration, use the dialog, and them maybe switch back. + m xmod --setmonitor MON-BOTTOM-LEFT $half_x/298x$half_y/336+$x_offset+$half_y none + m xmod --setmonitor MON-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none +fi + + +## begin i3 config ## +move_outputs=() +ws_outputs=() +if [[ $secondary_out ]]; then + ws1_output=$primary_out + move_outputs=($primary_out) +elif $tall || $quarter; then + ws1_output=MON-RIGHT +fi + +ws_outputs=( + $ws1_output +) + + +if $tall; then + ws_outputs+=( + MON-LEFT + MON-RIGHT + ) + move_outputs+=(MON-RIGHT) +elif $quarter; then + ws_outputs+=( + MON-LEFT + MON-BOTTOM-LEFT + MON-RIGHT + ) + move_outputs+=(MON-BOTTOM-LEFT MON-RIGHT) +elif [[ $secondary_out ]]; then + move_outputs+=($secondary_out) + ws_outputs+=($secondary_out) + +fi + +#echo d1 ${ws_outputs[@]} + +rm -f ~/i3-myx.conf +total_ws_count=11 +for (( i=0; i>~/i3-myx.conf + fi +done + +{ + cat /a/bin/ds/i3-sway/bar.conf + + ## for when we are temporarily 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 && $HOSTNAME != frodo ]]; then + echo "}" + else + echo 'mode hide +hidden_state hide +}' + fi + +} >> ~/i3-myx.conf + +if (( ${#move_outputs[@]} )); then + echo "bindsym \$mod+Shift+t move workspace to output next # set by myx" >>~/i3-myx.conf + #echo "bindsym \$mod+Shift+t move workspace to output ${move_outputs[*]} # set by myx" >>~/i3-myx.conf +else + echo "# bindsym \$mod+Shift+t move workspace to output XXX XXX # note: if we had logical X screen or multimons, this would be set by myx" >>~/i3-myx.conf +fi +# give it some time to reload or adjust to new x settings. + +# i3-msg -t get_outputs | jq -C . +# showed +# { +# "name": "HDMI-2", +# "active": true, +# "primary": false, +# "rect": { +# "x": 1920, +# "y": 0, +# "width": 3840, +# "height": 2160 +# }, +# "current_workspace": "3" +# }, +# { +# "name": "DP-1", +# "active": false, +# "primary": false, +# "rect": { +# "x": 1920, +# "y": 0, +# "width": 3840, +# "height": 2160 +# }, +# "current_workspace": null +# } +# This was incorrect. The correct thing is that DP-1 is active, HDMI-2 is not active. +# Restarting i3 did not help. + +sleep 1 +m /a/bin/ds/i3-sway/gen $gen_arg + +if (( ${#ws_outputs[@]} )); then + + declare -A ws_expected_out + + for (( i=0; i 20 )); then + cat <<'EOF' >&2 + +ERROR: moving workspaces is not working as expected I've seen it happen +that an output should not exist anymore. Restarting i3 fixed it, reloading did not. +This script did a restart, but it might need a sleep before doing so. +EOF + exit 1 + fi + refresh_count=$(( refresh_count + 1 )) + refresh_workspaces=false + tmps=$(i3 -t get_workspaces) + tmps=$(jq -r '.[] | .num, .output' <<<"$tmps") + while read -r ws; do + read -r output || break + if [[ $ws != [0-9] && $ws != 10 ]]; then + echo "$0: error: unexpected workspace found: $ws. continuing" + continue + fi + if [[ ${ws_expected_out[$ws]} != "$output" ]]; then + m i3 '[workspace="'$ws'"]' move workspace to output ${ws_expected_out[$ws]} + refresh_workspaces=true + break + fi + done <<<"$tmps" + done +fi +## end i3 config ## + + + +m /a/exe/input-setup + +echo -n "myx end: " +date "+%A, %B %d, %r, %S seconds" + + +# myx -f +# Tuesday, July 23, 05:54:37 PM, 37 seconds +# myx: xmod --delmonitor MON-LEFT +# myx: xmod --delmonitor MON-RIGHT +# myx: xmod --output DP-1 --right-of eDP-1 --mode 3840x2160 +# d1 eDP-1 DP-1 +# myx: /a/bin/ds/i3-sway/gen -r +# /a/bin/ds/i3-sway/gen: i3-msg restart +# [{"success":true}] +# myx: i3 [workspace="2"] move workspace to output DP-1 +# ERROR: No output matched +# [{"success":false,"error":"No output matched"}] +# /a/exe/myx:63: `i3-msg "$@"' returned 2 +# from /a/exe/myx:63:in `i3 [workspace="2"] move workspace to output DP-1' +# from /a/exe/myx:88:in `m i3 [workspace="2"] move workspace to output DP-1' +# from /a/exe/myx:330:in `main -f' +# /a/exe/myx: exiting with status 2 diff --git a/pkgs b/pkgs index f786c69..2be63fb 100644 --- a/pkgs +++ b/pkgs @@ -126,6 +126,7 @@ p3=( debug-me debootstrap debconf-doc + dejagnu devscripts ddcutil dillo diff --git a/primary-setup b/primary-setup index c5f528a..7587408 100755 --- a/primary-setup +++ b/primary-setup @@ -101,11 +101,14 @@ if dpkg -s rss2email &>/dev/null; then fi fi -if [[ $HOSTNAME == "$HOST2" ]]; then - m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user enable --now awatch.service ||: -else - m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user disable --now awatch.service ||: -fi +# commented because i'm trying out the status bar that stays hidden until super is +# pressed, which causes an awatch error. Don't feel like fixing it +# atm. +# if [[ $HOSTNAME == "$HOST2" ]]; then +# m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user enable --now awatch.service ||: +# else +# m sudo -u iank XDG_RUNTIME_DIR=/run/user/1000 systemctl --no-block --user disable --now awatch.service ||: +# fi # todo: whats going on here? figure out if this should be removed. diff --git a/system-status b/system-status index 92c5b85..1882ace 100755 --- a/system-status +++ b/system-status @@ -452,7 +452,7 @@ write-status() { mtest_found=true fi done - if (( mtest_count < 4 )); then + if (( mtest_count < 3 )); then mtest_found=true fi if $mtest_found; then