X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;ds=sidebyside;f=brc2;h=3b1d5ba270298d0329926c20719c38b5141f7c76;hb=ee27d59f1eea7a83b1764ec41bfb3015bb463a26;hp=ec5969fef4929276b151883fe698fd24d3c78c5e;hpb=86560196eb4ccc90a7c1d903de47fcb887656de4;p=distro-setup diff --git a/brc2 b/brc2 index ec5969f..3b1d5ba 100644 --- a/brc2 +++ b/brc2 @@ -1,6 +1,25 @@ #!/bin/bash -# Copyright (C) 2019 Ian Kelling -# SPDX-License-Identifier: AGPL-3.0-or-later +# 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 switch +# its license to GPL. + +# 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. + # this gets sourced. shebang is just for file mode detection @@ -10,9 +29,29 @@ if [[ $LESSHISTFILE == - ]]; then HISTFILE= c() { cd "$@"; } elif [[ $HISTFILE ]]; then - HISTFILE=$HOME/.bh + # use an alternate history file when we are streaming. + if [[ -e $HOME/.iank-stream-on ]]; then + HISTFILE=/a/bin/data/stream_hist + else + HISTFILE=$HOME/.bh + fi fi +# history personal +hip() { + history -c + HISTFILE=$HOME/.bh + history -r +} + +# history for streaming +his() { + history -c + HISTFILE=/a/bin/data/stream_hist + history -r +} + + source /a/bin/distro-setup/path-add-function path-add /a/exe # add this with absolute paths as needed for better security @@ -64,15 +103,6 @@ else 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 @@ -162,7 +192,7 @@ slemacs() { 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 @@ -319,10 +349,16 @@ tback() { # s sshfs bu@$host:/bu/home/md /bu/mnt -o reconnect,ServerAliveInterval=20,ServerAliveCountMax=30 -o allow_other edelayoff() { - echo all >/etc/exim4/no-delay-eximids + echo all >/var/spool/exim4/gw/.no-delay-eximids + if [[ $EUID == 0 ]]; then + chown iank:iank /var/spool/exim4/gw/.no-delay-eximids + fi } edelayon() { - echo >/etc/exim4/no-delay-eximids + echo >/var/spool/exim4/gw/.no-delay-eximids + if [[ $EUID == 0 ]]; then + chown iank:iank /var/spool/exim4/gw/.no-delay-eximids + fi } eqgo() { @@ -431,7 +467,7 @@ ralerts() { # remote alerts 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() { @@ -463,7 +499,7 @@ glue() { # usage: see above _iki-convert() { - local url url_prefix path input err repo_dir dir url_dir url name + local url url_prefix path input repo_dir dir url_dir url name url_prefix="$1" name="${url_prefix%%.*}" repo_dir="/f/$name" @@ -476,8 +512,16 @@ _iki-convert() { case $input in http*) path="$repo_dir/${input##http*://"$url_prefix"/}" + # for files like x.jpg, we dont need to convert the extension. if [[ $path == */ ]]; then path=${path%/}.mdwn + # brains adds trailing slash, but without trailing is still + # valid. We can't be totally sure whether to add mdwn, but we + # can guess based on the existence of the file. We can't be sure + # because it could be a file like x.jpg, that we just don't have + # in our local repo. + elif [[ ! -f $path && -e $path.mdwn ]]; then + path=${path}.mdwn fi j printf "%s\n" "$path" ;; @@ -485,7 +529,9 @@ _iki-convert() { path=$(fp "$input") url_dir=$(echo "$path" | sed -r "s,^(/a)?$repo_dir/,,") url="https://$url_prefix/$url_dir" - url="${url%.mdwn}/" + if [[ $url == *.mdwn ]]; then + url="${url%.mdwn}/" + fi j echo "$url" ;; esac @@ -748,6 +794,7 @@ mpvrpc-percent-pos() { # background, this relies on how ps converts newlines in arguments to spaces, and # assumes we won't be searching for a command with spaces in its arguments rinr() { + # shellcheck disable=SC2009 # pgrep has no fixed string option, plus see above. if ps h -o args -C "${1##*/}" | grep -Fxqv "$*" &>/dev/null || [[ $? == 141 ]]; then "$@" fi @@ -780,7 +827,7 @@ mpvrpc-loadfile() { finalpath="$cachedir${path#/i/m}" rowir rsync --partial -a --inplace --mkpath "b8.nz:$path" "$finalpath" finalnextpath="$cachedir${nextpath#/i/m}" - count=$(pgrep -a -f "^rsync --partial -a --inplace --mkpath $cachdir" || [[ $? == 1 ]] ) + count=$(pgrep -a -f "^rsync --partial -a --inplace --mkpath $cachedir" || [[ $? == 1 ]] ) # allow us to start 2 rsyncs in the background if [[ $count == [01] ]]; then rinr rsync --partial -a --inplace --mkpath "b8.nz:$nextpath" "$finalnextpath" & @@ -810,9 +857,10 @@ mpvrpc-loadfile() { # q quit # ret next # +# 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 @@ -877,7 +925,7 @@ beetag() { else pl_state_file=sorted fi - pl_state_dir=/i/info/pl-state + pl_state_dir=/b/data/pl-state if [[ $playlist ]]; then pl_state_dir=$pl_state_dir/$playlist else @@ -1482,7 +1530,6 @@ btrbk-host-debug() { # $ 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 / @@ -1661,11 +1708,9 @@ jdo() { 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 @@ -1730,7 +1775,13 @@ lipush() { local p a # excluding emacs for now #p=(/a/opt/{emacs-debian11{,-nox},mu,emacs} /a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts}) - p=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts} /c/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter /a/opt/fpaste) + p=( + /a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts} + /c/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter + /a/opt/fpaste + /p/c/user-specific/www-data/icecast-fsf{,-tech}-htpasswd + /p/c/icecast.xml + ) a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes" ret=0 for h in li je bk; do @@ -1761,19 +1812,13 @@ bindpush() { dsign iankelling.org expertpathologyreview.com zroe.org amnimal.ninja lipush for h in li bk; do - m sl $h.b8.nz <<'EOF' -source ~/.bashrc -m dnsup -EOF + m ssh iank@$h.b8.nz dnsup done } bindpushb8() { lipush for h in li bk; do - m sl $h <<'EOF' -source ~/.bashrc -m dnsb8 -EOF + m ssh $h.b8.nz dnsb8 done } @@ -1784,8 +1829,18 @@ dnsup() { 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 } @@ -1829,7 +1884,13 @@ dsign() { # 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 @@ -1875,68 +1936,12 @@ satoshi() { # $1 satoshi in usd # 2023). However, in 2024-02, I ran a backup where a receiving machine # had the wallet enabled and there was no error, so I don't know if this # is still an issue or likely it is an inconsistent behavior. +# Note: a pruned node won't allow for a wallet to be added, super lame +# so i'm just not running a bitcoin node for now. +# Error: Prune: last wallet synchronisation goes beyond pruned data. You +# need to -reindex (download the whole blockchain again in case of +# pruned node) # -# As a workaround, this function is for enabling the wallet when I want -# to use it and leave it disabled otherwise. -walleton() { - local active - active=false - no_on=true - if [[ ! $(readlink -f /var/lib/bitcoind/wallets) == /q/wallets ]]; then - if systemctl --quiet is-active bitcoind; then - if [[ -e /tmp/no-bitcoinon ]]; then - no_on=true - else - if [[ $EUID == 0 ]]; then - m install -T -o iank -g iank /dev/null /tmp/no-bitcoinon - else - m touch /tmp/no-bitcoinon - fi - fi - active=true - m ser stop bitcoind - fi - m s ln -s /q/wallets /var/lib/bitcoind - sudo chown -h bitcoin:bitcoin /var/lib/bitcoind/wallets - if $active; then - m ser start bitcoind - if ! $no_on; then - m rm /tmp/no-bitcoinon - fi - fi - fi -} -walletoff() { - local active - active=false - no_on=true - if [[ $(readlink -f /var/lib/bitcoind/wallets) == /q/wallets ]]; then - if systemctl --quiet is-active bitcoind; then - if [[ -e /tmp/no-bitcoinon ]]; then - no_on=true - else - if [[ $EUID == 0 ]]; then - m install -T -o iank -g iank /dev/null /tmp/no-bitcoinon - else - m touch /tmp/no-bitcoinon - fi - fi - active=true - m ser stop bitcoind - else - echo note: bitcoind not active - fi - m rm /var/lib/bitcoind/wallets - if $active; then - # note, starting bitcoin always fails, but it actually - # succeeds. But this is strangely not consistent. - m ser start bitcoind - if ! $no_on; then - m rm /tmp/no-bitcoinon - fi - fi - fi -} #### end bitcoin related things @@ -1962,6 +1967,75 @@ capache() fi } + + +apache-header() { + # First paragraph is to avoid people being confused about why a + # file is apache licensed. + cat <<'EOF' +# 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. + +EOF + +} + +# apply apache to git tracked bash files + README, except files with A?GPL3 header. +apache-apply-repo() { + for f in $(git ls-files); do + [[ -L $f || ! -f $f ]] && continue + if [[ $f != README ]]; then + if ! grep -n '^#!/bin/bash' $f | grep ^1: &>/dev/null; then continue; fi + if head -n 10 $f | grep 'it under the terms of the GNU General Public License as published by' &>/dev/null; then continue; fi + fi + apache-apply $f + done +} + +apache-apply() { + for file; do + if [[ ! -e $file ]]; then + echo '#!/bin/bash' >$file + chmod +x $file + fi + if head -n1 "$file"| grep -E '^#!/' &>/dev/null; then + { + head -n1 "$file" + apache-header + tail -n+2 "$file" + } | sponge "$file" + else + { + apache-header + cat "$file" + } | sponge "$file" + fi + done +} +# strip out the apache license from a file. +apache-strip() { + # shellcheck disable=SC2044 # meh + for f in $(find . -type f -maxdepth 1); do if head -n1 "$f"| grep -E '^#!/bin/bash\b' &>/dev/null; then { head -n 20 $f | tac | sed '/^# limitations under the License.$/,/^# Copyright.*Ian Kelling$/d' | tac; tail -n+21 $f; } |sponge $f; fi ; done +} + chrome() { if type -p chromium &>/dev/null; then cmd=chromium @@ -2062,7 +2136,7 @@ fastboot() { kdecd() { /usr/lib/x86_64-linux-gnu/libexec/kdeconnectd; } -bat() { +batp() { cat /sys/class/power_supply/BAT0/capacity } @@ -2249,8 +2323,8 @@ rename-test() { # 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 @@ -2302,8 +2376,8 @@ gup() { /a/f/gnulib/build-aux/gnupload "$@"; } 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)"/.. @@ -2317,6 +2391,16 @@ hstatus() { 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 @@ -2466,15 +2550,21 @@ ilog-local() { cd $d$n/"$chan" hr for x in *; do - echo $x; sed "s/^./${x%log}/" $x; hr; + # *** are parts and joins and such, and they make reading hard. + # I probably will want to see them sometimes, just have to + # remove that part. + echo $x; sed "s/^./${x%log}/;/\*\*\*/d" $x; hr; done 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() { @@ -2529,22 +2619,148 @@ wgkey() { umask $umask_orig } -declare -A vpn_ips -vpn_ips[kd]=2 -# note: 1, 4, 5 are occupied by mail wireguard -vpn_ips[x3]=8 -vpn_ips[sy]=12 -vpn_ips[x2]=13 -vpn_ips[kw]=27 -vpn_ips[bo]=28 -vpn_ips[frodo]=34 -vpn_ips[s23b]=49 +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 portfw_ips nonvpn_ips all_ips + local -a root_hosts nonroot_hosts + + # the hosts with no mac + root_hosts=( bk je li b8.nz ) + for h in ${root_hosts[@]}; do + root_hosts+=(${h}ex) + done + root_hosts+=(cmc) + + while read -r ip host mac opts; do + if [[ $ip == *#* || ! $host ]]; then continue; fi + + # 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 $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) + # shellcheck disable=SC2004 # false positive + root_hosts_a[$host]=t # a for associative array + else + nonroot_hosts+=($host ${host}i) + fi + host_ips[$host]=$ip + if [[ $mac ]]; then + host_macs[$host]=$mac + fi + + done
/p/c/cmc-firewall-data + -vpn-ips-update() { 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 <