export NOT_MAIL_HOST_P=t
fi
-
-source /a/bin/log-quiet/logq-function
-
-# not used
-# if [[ -s /a/opt/alacritty/extra/completions/alacritty.bash ]]; then
-# source /a/opt/alacritty/extra/completions/alacritty.bash
-# fi
-
-
source /a/bin/ds/beet-data
sle() { # sl emacs
local f=/home/iank/.emacs.d/init.el
- sl --sl-test-cmd ". /etc/os-release ; printf %s \${VERSION//[^a-zA-Z0-9]/}; test -e $f && stat -c%Y $f" --sl-test-hook slemacs "$@"
+ sl --sl-test-cmd "sed -rn '/^VERSION=/{s/^.*=//;s/[^[:alnum:]]//gp}' /etc/os-release; test -e $f && stat -c%Y $f" --sl-test-hook slemacs "$@"
}
ccomp ssh sle
ap() {
# pushd in case current directory has an ansible.cfg file
pushd /a/xans >/dev/null
- ansible-playbook -v -l ${1:- $(hostname -f)} site.yml
+ ansible-playbook -v -i ${1:- $(hostname -f)}, site.yml
popd >/dev/null
}
aw() {
# todo: enter should also unpause
beetag() {
local last_genre_i fstring tag id char new_item char_i genre tag remove doplay i j random path
- local do_rare_genres read_wait help line lsout tmp ls_line skip_lookback
+ local do_rare_genres read_wait line lsout tmp ls_line skip_lookback
local escape_char escaped_input expected_input skip_input_regex right_pad erasable_line seek_sec
local pl_state_path pl_state_dir pl_state_file tmpstr
local new_random pl_seed_path seed_num seed_file fmt first_play repeat1
# $ dig ns1.gnu.org @b0.org.afilias-nst.org.
-# todo: make sm pull/push use systemd instead of the journal cat command
bbk() { # btrbk wrapper
local ret=0
c /
if [[ $cmd != /* ]]; then
cmd=$(type -P "$cmd")
fi
+ #note date format for since is date '+%F %T'
# -q = quiet
- journalctl -qn2 -f -u "$cmd_name" &
- # Trial and error of time needed to avoid missing initial lines.
- # .5 was not reliable. 1 was not reliable. 2 was not reliable
- sleep 4
+ journalctl --since=now -qn2 -f -u "$cmd_name" &
jr_pid=$!
# note, we could have a version that does system --user, but if for example
# it does sudo ssh, that will leave a process around that we can't kill
dsign iankelling.org expertpathologyreview.com zroe.org amnimal.ninja
lipush
for h in li bk; do
- e sshing $h
- ssh $h.b8.nz <<'EOF'
-source ~/.bashrc
-m dnsup
-EOF
+ m ssh $h.b8.nz dnsup
done
}
bindpushb8() {
lipush
for h in li bk; do
- e sshing $h
- ssh $h.b8.nz <<'EOF'
-source ~/.bashrc
-m dnsb8
-EOF
+ m ssh $h.b8.nz dnsb8
done
}
dnsb8() {
local f=/var/lib/bind/db.b8.nz
m ser stop named
- m sleep 1
- m sudo rm -fv $f.jnl $f.signed.jnl
+ # jbk is like a temp file. dunno if removing it helps
+
+ i=0
+ while pgrep '^named$' &>/dev/null; do
+ sleep .5
+ i=$(( i + 1 ))
+ if (( i > 100 )); then
+ echo "dnsb8: error: timeout waiting for named to exit"
+ return 1
+ fi
+ done
+ m sudo rm -fv $f.jnl $f.signed.jnl $f.jbk
m sudo install -m 644 -o bind -g bind /p/c/machine_specific/vps/bind-initial/db.b8.nz $f
m ser restart named
}
# set day start for use in other programs.
# expected to do be in a format like 830, or 800 or 1300.
ds() {
+ local regex
+ regex='[0-9]?[0-9]?[0-9][0-9]'
if [[ $1 ]]; then
+ if [[ ! $1 =~ $regex ]]; then
+ echo "ds: error. expected \$1 to match $regex, got \$1: $1"
+ return 1
+ fi
echo $1 >/b/data/daystart
else
cat /b/data/daystart
# 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 switch
-# its license to GPL.
+# programs. If a small program grows beyond 300 lines, I plan to change
+# to a recommended GPL license.
# Copyright 2024 Ian Kelling
apache-apply() {
for file; do
- if head -n1 "$file"| grep -E '^#!/bin/bash\b' &>/dev/null; then
+ if head -n1 "$file"| grep -E '^#!/' &>/dev/null; then
{
head -n1 "$file"
apache-header
# test whether missing files were renamed, generally for use with fsdiff
# $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir
# echos non-renamed files
- local x y found
- unset sums
+ local x line found renamed
+ local -a sums
for x in "$2"/*; do
{ sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null
done
dejagnu() { /a/opt/dejagnu/dejagnu "$@"; }
+# do git status on published repos.
hstatus() {
- # do git status on published repos.
c /a/bin/githtml
for x in *; do
cd "$(readlink -f $x)"/..
done
}
+hsk() {
+ local x
+ c /a/bin/githtml
+ for x in *; do
+ cd "$(readlink -f $x)"/..
+ skgit
+ cd /a/bin/githtml
+ done
+}
+
## work log
#
# note: database location is specified in ~/.timetrap.yml, currently /p/.timetrap.db
done
}
ilog() {
- local chan
+ local chan tmpf
+ tmpf=$(mktemp)
chan="${1:-#fsfsys}"
# use * instead of -r since that does sorted order
- sl root@iankelling.org ilog-local "$chan" | less +G
+ sl root@li.b8.nz ilog-local "$chan" > $tmpf
+ less +G $tmpf
+ rm -f $tmpf
}
o() {
umask $umask_orig
}
+host-info-all() {
+ host-info-update
+
+ bindpushb8
+ # for wireguard configs
+ ssh iank@li.b8.nz conflink
+ wrt-setup
+}
+
+
+
+
+
+## for updating host info like ip, location, update /p/c/host-info and
+## host_info below. the host_info array should probably be in its own
+## file that gets sourced so that it can be more easily updated.
+
+# todo: this is so long that it becomes confusing,
+# try to split it up.
+#
+# To make some changes take effect, run host-info-all.
host-info-update() {
- local -A vpn_ips host_ips host_macs nonvpn_ips
+ local -A vpn_ips host_ips host_macs portfw_ips nonvpn_ips all_ips
local -a root_hosts nonroot_hosts
# the hosts with no mac
while read -r ip host mac opts; do
if [[ $ip == *#* || ! $host ]]; then continue; fi
- if [[ $opts == vpn ]]; then
+
+ # opt parsing
+ vpn=false
+ root=false
+ for opt in $opts; do
+ case $opt in
+ user=root)
+ root=true
+ ;;
+ vpn)
+ vpn=true
+ ;;
+ esac
+ done
+
+ all_ips[$host]=$ip
+ if $vpn; then
+ portfw_ips[$host]=$ip
vpn_ips[$host]=$ip
else
nonvpn_ips[$host]=$ip
fi
-
-
- if [[ $opts == user=root ]]; then
- # note: the b8.nz suffix is for the User part, the IdentityFile
- # part is redundant to *.b8.nz.
- root_hosts+=($host i$host $host.b8.nz i$host.b8.nz)
+ if $root; then
+ # note: the reason we have b8.nz suffix here but not for non_root
+ # hosts is that it is for the User part, the IdentityFile part is
+ # redundant to *.b8.nz. Also note ${host}i, we only setup those for vpn hosts, but there is no harm in overspecifying here.
+ root_hosts+=($host ${host}i $host.b8.nz ${host}i.b8.nz)
+ root_hosts_a[$host]=t # a for associative array
else
- nonroot_hosts+=($host i$host)
+ nonroot_hosts+=($host ${host}i)
fi
-
host_ips[$host]=$ip
- host_macs[$host]=$mac
+ if [[ $mac ]]; then
+ host_macs[$host]=$mac
+ fi
+
done </p/c/host-info
- cedit /p/c/subdir_files/.ssh/config <<EOF || [[ $? == 1 ]]
+ {
+ cat <<EOF
Host ${nonroot_hosts[@]}
User iank
IdentityFile ~/.ssh/home
Host ${root_hosts[@]}
IdentityFile ~/.ssh/home
+
+EOF
+ for host in ${!vpn_ips[@]}; do
+ ipsuf=${vpn_ips[$host]}
+ cat <<EOF
+Host ${host}i ${host}i.b8.nz
+Port $((2200 + ipsuf))
EOF
+ done
+ # convenience of one auth key entry
+ for host in ${!all_ips[@]}; do
+ cat <<EOF
+Host $host ${host}i $host.b8.nz ${host}i.b8.nz
+HostKeyAlias $host.b8.nz
+EOF
+ done
+ } | cedit -e /p/c/subdir_files/.ssh/config-static
+
+ {
+ # hack to please emacs parser
+ here_begin="cat <<EOF"
+ echo "$here_begin"
+ for host in ${!vpn_ips[@]}; do
+ ipsuf=${vpn_ips[$host]}
+ i_port=$(( 2200 + ipsuf ))
+ cat <<EOF
+config redirect
+option name ssh$host
+option src wan
+option src_dport $i_port
+option dest_port 22
+option dest_ip \$l.$ipsuf
+option dest lan
+config rule
+option src wan
+option target ACCEPT
+option dest_port $i_port
+EOF
+ done
+ echo "EOF"
+ } >/p/c/cmc-firewall-data
- grep -E '^[a-z0-9]+[[:space:]]' /p/c/machine_specific/vps/bind-initial/db.b8.nz | awk '{print $1,$3}'
local host ipsuf f files
+ # shellcheck disable=SC2016 # shellcheck doesnt know this is sed
sedi '/edits below here are made automatically/,$d' /p/c/machine_specific/li/filesystem/etc/wireguard/wgmail.conf
for host in ${!vpn_ips[@]}; do
+ if [[ ${root_hosts_a[$host]} ]]; then
+ # root machines dont actually need vpn, but
+ # the classification still helps with other
+ # configurations.
+ continue
+ fi
ipsuf=${vpn_ips[$host]}
wghole $host $ipsuf
+ u /b/ds/machine_specific/li/filesystem/etc/openvpn/client-config-hole/$host <<EOF
+ifconfig-push 10.5.5.${vpn_ips[$host]} 255.255.255.0
+EOF
u /a/bin/ds/machine_specific/$host/filesystem/etc/systemd/system/openvpn-client-tr@.service <<EOF
[Unit]
Description=OpenVPN tunnel for %I
echo "cat <<EOF"
for host in ${!host_ips[@]}; do
ipsuf=${host_ips[$host]}
+ # shellcheck disable=SC2016 # intentional
echo 'local-data-ptr: "$l.'$ipsuf $host.b8.nz'"'
done
echo "EOF"
- } | u /p/ptr-data
+ } | u /p/c/ptr-data
{
echo "cat <<EOF"
- for host in ${!host_ips[@]}; do
+ for host in ${!host_macs[@]}; do
ipsuf=${host_ips[$host]}
echo "dhcp-host=${host_macs[$host]},set:$host,\$l.$ipsuf,$host"
done
echo "EOF"
- } | u /p/dnsmasq-data
+ } | u /p/c/dnsmasq-data
+
+ b8_ip=$(dig +short b8.nz @iankelling.org | tail -1)
+ if [[ ! $b8_ip ]]; then
+ echo "$0: error: got empty b8.nz ip. returning 1"
+ return 1
+ fi
{
+ echo "@ A $b8_ip"
for host in ${!nonvpn_ips[@]}; do
ipsuf=${nonvpn_ips[$host]}
echo "$host A 10.2.0.$ipsuf"
${host}wg A 10.8.0.$ipsuf
${host}vp A 10.5.5.$ipsuf
${host}tr A 10.174.$ipsuf.2
+${host}i A $b8_ip
EOF
done
- } | cedit vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz ||:
+ } | cedit -e vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz
echo checking for stray files:
- initial_dir=$PWD
- cd /a/bin/ds/machine_specific
- ngset
- files=( */filesystem/etc/systemd/system/openvpn-client-tr@.service )
- ngreset
- cd $initial_dir
+ initial_dir="$PWD"
+ while read -r dir path; do
+ cd $dir
+ ngset
+ files=( */$path )
+ ngreset
+ cd "$initial_dir"
+ for f in "${files[@]}"; do
+ host=${f%%/*}
+ if [[ ! ${vpn_ips[$host]} ]]; then
+ e rm $dir/$f
+ fi
+ done
+ done <<'EOF'
+/a/bin/ds/machine_specific filesystem/etc/systemd/system/openvpn-client-tr@.service
+/p/c/machine_specific filesystem/etc/wireguard/wghole.conf
+EOF
+
+ files=( /b/ds/machine_specific/li/filesystem/etc/openvpn/client-config-hole/* )
for f in "${files[@]}"; do
- host=${f%%/*}
+ host=${f##*/}
if [[ ! ${vpn_ips[$host]} ]]; then
- e /a/bin/ds/machine_specific/$host/filesystem/etc/systemd/system/openvpn-client-tr@.service
+ e rm $f
+ e ssh root@li.b8.nz rm -f $f
fi
done
- cd /p/c/machine_specific
- ngset
- files=( */filesystem/etc/wireguard/wghole.conf )
- ngreset
- cd $initial_dir
- for f in "${files[@]}"; do
- host=${f%%/*}
- if [[ ! ${vpn_ips[$host]} ]]; then
- e rm /p/c/machine_specific/$host/filesystem/etc/wireguard/wghole.conf
+ tmpf=$(mktemp)
+ {
+ printf "%s" "Host * "
+ sed -n '/^Host /h;/^IdentityFile .*\/home/{g;s/^Host//;s/ / !/gp}' /p/c/subdir_files/.ssh/config-static | tr '\n' ' '
+ echo
+ echo "IdentityFile ~/.ssh/work"
+ } >$tmpf
+ cedit -e work-identity /p/c/subdir_files/.ssh/config-static <$tmpf
+ rm -f $tmpf
+
+ ### begin focus on hosts file update ###
+ #
+ # This started as its own function, but it actually
+ # needed to alter the ssh config, so combined it.
+ #
+ # background: This is finally doing dynamic ip resolution via the hosts
+ # file. I considered detecting where each host was dynamically or
+ # something, but ultimately decided to mostly avoid that, other than
+ # detecting the status of the current machine I'm on. I want to be able
+ # to move it around without having to manually type much of anything.
+ local -a host_domain_suffix hosts
+ local -A ip_to_hosts
+ local suf ip i host at_home suf_from_here
+
+ source /p/c/domain-info
+
+ at_home=false
+ if ip n | grep -q "10.2.0.1 .* b4:75:0e:fd:06:4a"; then
+ at_home=true
+ fi
+
+ for i in ${host_domain_suffix[@]}; do
+ if [[ $i == *.* ]]; then
+ suf=$i
+ continue
+ fi
+ hosts+=($i)
+ if [[ $i == "$HOSTNAME" ]]; then
+ unset "portfw_ips[$i]"
+ continue
fi
+
+ suf_from_here=$suf
+ if ! $at_home && [[ $suf == .b8.nz || $suf == [wc].b8.nz ]]; then
+ suf_from_here=i.b8.nz
+ else
+ unset "portfw_ips[$i]"
+ fi
+
+ ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -n1) ||:
+ if [[ ! $ip ]]; then
+ if [[ $suf == .office.fsf.org ]]; then
+ suf_from_here=wg.b8.nz
+ ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -n1) ||:
+ fi
+ if [[ ! $ip ]]; then
+ echo error: failed to get ip of "$i$suf_from_here"
+ return 1
+ fi
+ fi
+ ip_to_hosts[$ip]+=" $i"
done
+
+ for ip in "${!ip_to_hosts[@]}"; do
+ echo "$ip${ip_to_hosts[$ip]}"
+ done | s cedit -e hosts-file-up /etc/hosts
+ for host in ${hosts[@]}; do
+ echo $host
+ done >/p/c/subdir_files/.dsh/group/btrbk
+ ### end focus on hosts file update ###
+
+
+ # note: note sure if this is a great way to check.
+ # todo: think about it
+
+ if $at_home; then
+ # possible that in the future we want to create
+ # a dynamic file here, and then we can move the cat
+ # command above out of the conditional
+ rsync -a /p/c/subdir_files/.ssh/config-static ~/.ssh/config
+ else
+ for host in ${!portfw_ips[@]}; do
+ ipsuf=${portfw_ips[$host]}
+ cat <<EOF
+Host ${host}
+Port $((2200 + ipsuf))
+EOF
+ done > ~/.ssh/config-dynamic
+ cat /p/c/subdir_files/.ssh/config-static ~/.ssh/config-dynamic >~/.ssh/config
+ fi
}
# usage host ipsuf [extrahost]
pushd /home/iank/.local/share/profanity/chatlogs/iank_at_fsf.org/rooms/office_at_conference.fsf.org
logs=(*)
logcount=${#logs[@]}
- if (( logcount > 15 )); then
- i=$(( logcount - 15 ))
+ if (( logcount > 16 )); then
+ i=$(( logcount - 16 ))
else
i=0
fi
fi
[[ $1 ]] || { echo need arg; return 1; }
- journalctl --unit=$vpn_service@$1 -f -n0 &
- # sometimes the journal doesnt open until after the vpn output
- # has happened. hoping this fixes that.
- sleep 1
+ journalctl --since=now --unit=$vpn_service@$1 -f -n0 &
sudo systemctl start $vpn_service@$1
# sometimes the ask-password agent does not work and needs a delay.
sleep .5
fi
}
-# unmute
+# unmute desktop output
um() {
- local sink card
+ local sink card sedcmd
sink=$(pactl get-default-sink)
if [[ $sink == auto_null ]]; then
# guessing there is just one with an off profile. otherwise we will
# need some other solution, like storing the card identifier that we
- # muted with nap.
- card=$(pacmd list-cards | sed -n '/^[[:space:]]*index:/{s/^[[:space:]]*index://;h};/^[[:space:]]*active profile: <off>$/{g;p;q}')
+ # muted with nap. Or, we could so some hakery with
+ # pactl -f json.
+ sedcmd='/^[[:space:]]*index:/{s/^[[:space:]]*index://;h};/^[[:space:]]*active profile: <off>$/{g;p;q}'
+ card=$(pacmd list-cards | sed -n "$sedcmd")
m pacmd set-card-profile "$card" output:analog-stereo
fi
}
+# grep + find
+gef() {
+ faf | grep -E "$@" ||:
+ rgv "$@"
+}
+
# rg my main files
rgm() {
rg "$@" /p/w.org /a/t.org /a/work.org /b
}
# re all my files more expansively
-
rem() {
local paths
paths="/p/c /b/"
case $HOSTNAME in
sy|kd)
hosts=(
- kd x3.office.fsf.org syw
+ kd.b8.nz x3.office.fsf.org syw x2.b8.nz
)
;;
x3)
units "tempF($1)" tempC
}
-# requires dns/firewall setup first
+# note: requires dns setup of live.iankelling.org, & if i'm home, port
+# forwarding in wrt-setup-local. todo: automate that.
local-icecast() {
web-conf -e ian@iankelling.org -f 8000 - apache2 live.iankelling.org <<'EOF'
<Location "/fsf.webm">
done
}
+opensslcertinfo() {
+ openssl x509 -txt -in "$@"
+}
+
+# dsh on btrbk hosts
+dsb() {
+ :
+}
+
+# dsh a file and run it
+dsa() {
+ local ret file
+ if ! parallel -j 10 scp x {}:/tmp <~/.dsh/group/btrbk; then
+ echo parallel scp failed. dsa returning $ret
+ fi
+ dsh -g btrbk
+}
+
+# temporary
+zmqsend() {
+ /nocow/t/ffmpeg-release/ffmpeg-7.0.1/tools/zmqsend "$@"
+}
+
+ffg() { /nocow/t/ffmpeg-release/ffmpeg-7.0.1/tools/graph2dot -o /tmp/g.tmp && dot -Tpng /tmp/g.tmp -o /tmp/g.png && feh /tmp/g.png; }
export BASEFILE_DIR=/a/bin/fai-basefiles