X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=brc;h=138fd896b26df6b2ae9361ba75709abd9855fe93;hb=103a2e153f844343c359882079936b2521c82f15;hp=0b89b663c9173b0f0aedb0c7cc87420bd247ce89;hpb=7b47d6a266340223e78317cfe0570868f45a4cad;p=distro-setup diff --git a/brc b/brc index 0b89b66..138fd89 100644 --- a/brc +++ b/brc @@ -141,6 +141,7 @@ if ! type -p stty >/dev/null; then fi +use_color=false if [[ $- == *i* ]]; then # for readline-complete.el if [[ $LC_INSIDE_EMACS ]]; then @@ -151,6 +152,11 @@ if [[ $- == *i* ]]; then bind '"\C-i": self-insert' else + + if [[ $TERM != dumb ]] && test -t 1; then + use_color=true + fi + if [[ $KONSOLE_PROFILE_NAME ]]; then TERM=xterm-256color fi @@ -198,6 +204,15 @@ if [[ $- == *i* ]]; then fi +case $TERM in + # fixup broken backspace in chroots + xterm-kitty|alacritty) + chroot() { + TERM=xterm-256color command chroot "$@" + } + ;; +esac + export BC_LINE_LENGTH=0 # ansible option @@ -223,8 +238,7 @@ export SL_INFO_DIR=/p/sshinfo if [[ -s $bashrc_dir/path-add-function ]]; then source $bashrc_dir/path-add-function if [[ $SSH_CLIENT ]]; then - # [[ -d /home/iank/.iank/e/e ]] mounts it unnecessarily, so use this. - if grep -qF /home/iank/.iank/e/e /etc/auto.iank /etc/exports &>/dev/null; then + if grep -qF /home/iank/.iank/e/e /etc/exports &>/dev/null; then export EMACSDIR=/home/iank/.iank/e/e fi path-add $bashrc_dir @@ -245,11 +259,6 @@ if [[ $SOE ]]; then fi fi -# based on readme.debian. dunno if this will break on other distros. -if [[ -s /usr/share/wcd/wcd-include.sh ]]; then - source /usr/share/wcd/wcd-include.sh -fi - mysrc() { local path dir file @@ -322,8 +331,9 @@ fpst() { # file paste } _khfix_common() { - local host ip port + local host ip port file key read -r host ip port < <(timeout -s 9 2 ssh -oBatchMode=yes -oControlMaster=no -oControlPath=/ -v $1 |& sed -rn "s/debug1: Connecting to ([^ ]+) \[([^\]*)] port ([0-9]+).*/\1 \2 \3/p" ||: ) + file=$(readlink -f ~/.ssh/known_hosts) if [[ ! $ip ]]; then echo "khfix: ssh failed" return 1 @@ -335,11 +345,17 @@ _khfix_common() { ip_entry=$ip host_entry=$host fi + tmpfile=$(mktemp) if [[ $host != $ip ]]; then - m ssh-keygen -R "$host_entry" -f $(readlink -f ~/.ssh/known_hosts) - ll ~/.ssh/known_hosts + key=$(ssh-keygen -F "$host_entry" -f $file | sed -r 's/^.*([^ ]+ +[^ ]+) *$/\1/') + if [[ $key ]]; then + grep -Fv "$key" "$file" | sponge "$file" + fi + fi + key=$(ssh-keygen -F "$ip_entry" -f $file | sed -r 's/^.*([^ ]+ +[^ ]+) *$/\1/') + if [[ $key ]]; then + grep -Fv "$key" "$file" | sponge "$file" fi - m ssh-keygen -R "$ip_entry" -f $(readlink -f ~/.ssh/known_hosts) ll ~/.ssh/known_hosts rootsshsync } @@ -370,25 +386,255 @@ for num in {1..9}; do done -b() { - # backwards - c - +hexipv4() { + printf '%d.%d.%d.%d\n' $(echo $1 | sed 's/../0x& /g') } +vp9() { + local f out outdir in + outdir=vp9 + case $1 in + --out) + outdir=$2 + shift 2 + ;; + esac + m mkdir -p $outdir + for f; do + out=$PWD/$outdir/$f + in=$PWD/$f + m cd $(mktemp -d) + pwd + m ffmpeg -threads 0 -i $in -g 192 -vcodec libvpx-vp9 -vf scale=-1:720 -max_muxing_queue_size 9999 -b:v 750K -pass 1 -an -f null /dev/null + m ffmpeg -y -threads 0 -i $in -g 192 -vcodec libvpx-vp9 -vf scale=-1:720 -max_muxing_queue_size 9999 -b:v 750K -pass 2 -c:a libvorbis -qscale:a 5 $out + cd - + done +} -# c. better cd -if type -p wcd &>/dev/null; then - if [[ $LC_INSIDE_EMACS ]]; then - c() { wcd -c -z 50 -o "$@"; } - else - # lets see what the fancy terminal does from time to time - c() { wcd -c -z 50 "$@"; } +utcl() { # utc 24 hour time to local hour 24 hour time + echo "print( ($1 $(date +%z | sed -r 's/..$//;s/^(-?)0*/\1/')) % 24)"|python3 +} + +declare -a _iankdirf _iankdirb + + +# ## old wcd, to be deleted +# b() { +# # backwards +# c - +# } +# # shellcheck disable=SC2032 +# f() { +# # cd forward +# c + +# } +# cl() { +# # choose recent directory. cl = cd list +# c = +# } +# # c. better cd +# if ! type -t c &>/dev/null; then +# if type -p wcd &>/dev/null; then +# if [[ $LC_INSIDE_EMACS ]]; then +# c() { wcd -c -z 50 -o "$@"; } +# else +# # lets see what the fancy terminal does from time to time +# c() { wcd -c -z 50 "$@"; } +# fi +# else +# c() { cd "$@"; } +# fi +# fi + +# c. better cd. +# keep 2 stacks, forward and back. the top of the back is $PWD +# as long as the last directory change was due to c,b,or cl. +c() { + # normally, the top of dirb is our current dir. if it isn't, + # put it on there, except we don't want to do that when we + # just launched a shell + if [[ $OLDPWD ]]; then + if (( ${#_iankdirb[@]} == 0 )) || [[ ${_iankdirb[-1]} != "$PWD" ]]; then + _iankdirb+=("$PWD") + fi fi -else - c() { cd "$@"; } -fi + cd "$@" + if (( ${#_iankdirb[@]} == 0 )) || [[ ${_iankdirb[-1]} != "$PWD" ]]; then + _iankdirb+=("$PWD") + fi + echo "$PWD" >> ~/.iankdirs +} ccomp cd c +bwm() { + s bwm-ng -T avg -d +} + +b() { + local topb + if (( ${#_iankdirb[@]} == 0 )); then + echo "nothing left to go back to" >&2 + return 0 + fi + topb="${_iankdirb[-1]}" + + if [[ $topb == "$PWD" ]] && (( ${#_iankdirb[@]} == 1 )); then + echo "already on last back entry" >&2 + return 0 + fi + + + if [[ $topb == "$PWD" ]]; then + # add to dirf if not already there + if (( ${#_iankdirf[@]} == 0 )) || [[ ${_iankdirf[-1]} != "$topb" ]]; then + _iankdirf+=("$topb") + fi + unset "_iankdirb[-1]" + cd "${_iankdirb[-1]}" + else + if (( ${#_iankdirf[@]} == 0 )) || [[ ${_iankdirf[-1]} != "$PWD" ]]; then + _iankdirf+=("$PWD") + fi + cd "$topb" + fi + + # give us a peek at what is next in the list + # if (( ${#_iankdirb[@]} >= 2 )); then + # printf "%s\n" "${_iankdirb[-2]}" + # fi +} + +f() { + local topf + if (( ${#_iankdirf[@]} == 0 )); then + echo "no forward dir left" >&2 + return 0 + fi + topf="${_iankdirf[-1]}" + unset "_iankdirf[-1]" + c "$topf" + + # give us a peek at what is next in the list + # if (( ${#_iankdirf[@]} )); then + # printf "%s\n" "${_iankdirf[-1]}" + # fi +} + +# a b c (d) +## back +# a b (c) +# d +#back +#a (b) +#d c +#back +#(a) +#d c b +#forward +#a (b) +#d c +# +# a b c +## back +# a b +# (c) +## forward + +cl() { + local i line input start tmpfile + local -A buttondirs alines + local -a buttons dirs lines + buttons=( {a..z} {2..9} ) + if [[ ! -s ~/.iankdirs ]]; then + echo nothing in ~/.iankdirs + return 0 + fi + + i=0 + + # note, alternate approach like this, made the following read fail + # done < <(tac ~/.iankdirs | awk '!seen[$0]++') + # bash: read: read error: 0: Input/output error + # which went away by adding a sleep 1 after it. + + mapfile -t lines <~/.iankdirs + start=$(( ${#lines[@]} - 1 )) + + # we have ~33 buttons as of this writing, so lets + # prune down the history every once in a while. + if (( start > 500 )); then + tmpfile=$(mktemp) + tac ~/.iankdirs | awk '!seen[$0]++' | head -n 200 >$tmpfile + cat $tmpfile > ~/.iankdirs + fi + + for (( j=$start; j >= 0; j-- )); do + line="${lines[$j]}" + if [[ ! $line || ${alines[$line]} || ! -d "$line" || $line == "$PWD" || line == "$HOME" ]]; then + continue + fi + alines[$line]=t + buttondirs[${buttons[i]}]="$line" + printf "%s %s\n" ${buttons[i]} "$line" + if (( i == ${#buttons[@]} - 1 )); then + break + fi + i=$(( i + 1 )) + done + + if (( i == 0 )); then + echo "no dirs in ~/.iankdirs" + return 0 + fi + read -r -N 1 input + if [[ $input != $'\n' ]]; then + c ${buttondirs[$input]} + fi +} +bl() { + local start i j max + max=10 + start=$(( ${#_iankdirb[@]} - 1 )) + + # cleanup possible repeating of pwd + if (( start >= 0 )) && [[ ${_iankdirb[$start]} == "$PWD" ]]; then + start=$(( start - 1 )) + fi + j=1 + if (( start >= 0 )); then + for (( i=$start; i >= 0 ; i-- )); do + printf "%s %s\n" $j ${_iankdirb[i]} + j=$(( j + 1 )) + if (( j >= max )); then + break + fi + done + fi + + max=10 + + start=$(( ${#_iankdirf[@]} - 1 )) + + # cleanup possible repeating of pwd + if (( start >= 0 )) && [[ ${_iankdirf[$start]} == "$PWD" ]]; then + start=$(( start - 1 )) + fi + if (( start < 0 )); then + return 0 + fi + echo -- + j=1 + for (( i=$start; i >= 0 ; i-- )); do + printf "%s %s\n" $j ${_iankdirf[i]} + j=$(( j + 1 )) + if (( j >= max )); then + break + fi + done +} + + + c4() { c /var/log/exim4; } caa() { git commit --amend --no-edit -a; } @@ -434,7 +680,17 @@ chrbind() { for d in dev proc sys dev/pts; do [[ -d $d ]] if ! mountpoint $d &>/dev/null; then - s mount -o bind /$d $d + m s mount -o bind /$d $d + fi + done +} +chumount() { + local d + # dev/pts needed for pacman signature check + for d in dev/pts dev proc sys; do + [[ -d $d ]] + if mountpoint $d &>/dev/null; then + m s umount $d fi done } @@ -483,8 +739,8 @@ cdiff() { cat-new-files() { local start=$SECONDS local dir="$1" - inotifywait -m "$dir" -e create -e moved_to | - # shellcheck disable=SC2030 + # shellcheck disable=SC2030 + inotifywait -m "$dir" -e create -e moved_to | \ while read -r filedir _ file; do cat "$filedir$file" hr @@ -510,10 +766,6 @@ cim() { git commit -m "$*" } -cl() { - # choose recent directory. cl = cd list - c = -} d() { builtin bg "$@"; } ccomp bg d @@ -531,6 +783,19 @@ despace() { done } +# get ipv4 ip from HOST. or if it is already a number, return that +hostip() { + local host="$1" + case $host in + [0-9:]) + echo "$host" + ;; + *) + getent ahostsv4 "$host" | awk '{ print $1 }' | head -n1 + ;; + esac +} + dig() { command dig +nostats +nocmd "$@" } @@ -568,7 +833,10 @@ digdiff() { dt() { date "+%A, %B %d, %r" "$@" } -ccomp date dt +dtr() { + date -R "$@" +} +ccomp date dt dtr dus() { # du, sorted, default arg of du -sh ${@:-*} | sort -h @@ -576,7 +844,7 @@ dus() { # du, sorted, default arg of ccomp du dus -e() { echo "$@"; } +e() { printf "%s\n" "$*"; } # echo args ea() { @@ -594,8 +862,12 @@ ev() { echo no args fi for arg; do - printf "%qEOL\n" "${!arg}" - printf "%s" "${!arg}" |& hexdump -C + if [[ -v $arg ]]; then + printf "%qEOL\n" "${!arg}" + printf "%s" "${!arg}" |& hexdump -C + else + echo arg $arg is unset + fi done } @@ -608,7 +880,11 @@ ediff() { etail() { tail -F /var/log/exim4/mainlog -n 200 "$@" } -ccomp tail etail +etail2() { + tail -F /var/log/exim4/mymain -n 200 "$@" +} + +ccomp tail etail etail2 # print exim old pids eoldpids() { @@ -668,14 +944,18 @@ eless() { } ccomp less eless eqcat() { - exiqgrep -i -o 60 | while read -r i; do + exiqgrep -ir.\* -o 60 | while read -r i; do hlm exim -Mvc $i echo hlm exigrep $i /var/log/exim4/mainlog | cat ||: done } eqrmf() { - exiqgrep -i | xargs exim -Mrm + # other ways to get the list of message ids: + # exim -bp | awk 'NF == 4 {print $3}' + # # this is slower 160ms, vs 60. + # exipick -i + exiqgrep -ir.\* | xargs exim -Mrm } econfdevnew() { @@ -692,11 +972,6 @@ econfdev() { -# shellcheck disable=SC2032 -f() { - # cd forward - c + -} fa() { # find array. make an array of file names found by find into $x @@ -713,19 +988,15 @@ faf() { # find all files. use -L to follow symlinks -o -name .undo-tree-history -prune \) -type f 2>/dev/null } -# todo: id like to do maybe a daily or hourly cronjob to -# check that my history file size is increasing. Ive had it -# inexplicably truncated in the past. -histrm() { - history -n - history | awk -v IGNORECASE=1 '{ a=$1; sub(/^( *[^ ]+){4} */, "") }; /'"$*"'/' - read -p "press anything but contrl-c to delete" - for entry in $(history | awk -v IGNORECASE=1 '{ a=$1; sub(/^( *[^ ]+){4} */, "") }; /'"$*"'/ { print a }' | tac); do - history -d $entry - done - history -w +# full path without resolving symlinks +fp() { + local dir base + base="${1##*/}" + dir="${1%$base}" + printf "%s/%s\n" $(cd $dir; pwd) "$base" } + # mail related frozen() { rm -rf /tmp/frozen @@ -957,6 +1228,11 @@ ic() { git commit -am "$*" } +ipp() { + git pull + git push +} + ifn() { # insensitive find @@ -1050,7 +1326,7 @@ low() { # make filenames lowercase, remove bad chars fi f="${arg##*/}" new="${f,,}" # downcase - new="${new//[^[:alnum:]._-]/_}" # sub bad chars + new="${new//[^a-zA-Z0-9._-]/_}" # sub bad chars new="${new#"${new%%[[:alnum:]]*}"}" # remove leading/trailing non-alnum new="${new%"${new##*[[:alnum:]]}"}" # remove bad underscores, like __ and _._ @@ -1074,10 +1350,28 @@ lower() { # make first letter of filenames lowercase. k() { # history search grep -iP --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | tail -n 80 || [[ $? == 1 ]]; } -ks() { # history search +ks() { # history search with context + # args are an extended regex used by sed + history | sed -nr "h;s/^\s*(\S+\s+){4}//;/$*/{g;p}" | tail -n 80 || [[ $? == 1 ]]; +} +ksu() { # history search unique grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | uniq || [[ $? == 1 ]]; } -ccomp grep k ks + +# todo: id like to do maybe a daily or hourly cronjob to +# check that my history file size is increasing. Ive had it +# inexplicably truncated in the past. +histrm() { + history -n + HISTTIMEFORMAT= history | awk -v IGNORECASE=1 '{ a=$1; sub(/^ *[^ ]+ */, "") }; /'"$*"'/' + read -p "press anything but contrl-c to delete" + for entry in $(HISTTIMEFORMAT= history | awk -v IGNORECASE=1 '{ a=$1; sub(/^ *[^ ]+ */, "") }; /'"$*"'/ { print a }' | tac); do + history -d $entry + done + history -w +} + +ccomp grep k ks ksu histrm make-targets() { @@ -1113,7 +1407,15 @@ nags() { } nmt() { - s nmtui-connect "$@" + # cant use s because sudo -i doesnt work for passwordless sudo command + case $EUID in + 0) + sudo nmtui-connect "$@" + ;; + *) + nmtui-connect "$@" + ;; + esac } nopanic() { @@ -1252,6 +1554,13 @@ rsu() { # [OPTS] HOST PATH } ccomp rsync rsd rsa rst rsu +# find programs listening on a port +ssp() { + local port=$1 + # to figure out these args, i had to look at the man page from git version, as of 2022-04. + s ss -lpn state listening sport = $port +} + resolvcat() { local f if [[ $(systemctl is-active nscd ||:) != inactive ]]; then @@ -1259,7 +1568,7 @@ resolvcat() { fi f=/etc/resolv.conf echo $f:; ccat $f - hr; s ss -lpn 'sport = 53' + hr; s ss -lpn sport = 53 if systemctl is-enabled dnsmasq &>/dev/null || [[ $(systemctl is-active dnsmasq ||:) != inactive ]]; then # this will fail is dnsmasq is failed hr; m ser status dnsmasq | cat || : @@ -1274,7 +1583,7 @@ resolvcat() { grep '^ *hosts:' /etc/nsswitch.conf if systemctl is-enabled systemd-resolved &>/dev/null || [[ $(systemctl is-active systemd-resolved ||:) != inactive ]]; then hr; m ser status systemd-resolved | cat || : - hr; m systemd-resolve --status | cat + hr; m resolvectl status | cat fi } @@ -1303,6 +1612,10 @@ rmstrips() { ssh fencepost head -n 300 /gd/gnuorg/EventAndTravelInfo/rms-current-trips.txt | less } +sudo () { + command sudo "$@" || return $? + DID_SUDO=true +} s() { # background # I use a function because otherwise we cant use in a script, @@ -1345,7 +1658,6 @@ safe_rename() { # warn and dont rename if file exists. } - sd() { sudo dd status=none of="$1" } @@ -1361,6 +1673,10 @@ ser() { s service $2 $1 fi } +serstat() { + systemctl -n 40 status "$@" +} + seru() { systemctl --user "$@"; } # like restart, but do nothing if its not already started srestart() { @@ -1415,16 +1731,17 @@ sgu() { sk() { - # 2029: "unescaped, this expands on the client side." yes, I know how ssh works - # 2164: "Use 'cd ... || exit' or 'cd ... || return' in case cd fails." i have automatic error handling - # 2086: unquoted $var - # 2046: unquoted $(cmd) - # 2068: Double quote array expansions to avoid re-splitting elements. - # 2119: Functions with optional args get bad warnings when none are passed. - # 2033: too many false positives for thing that will never work, passing shell function to find. - # i had -x as an arg, but debian testing(stretch) doesn\'t support it - shellcheck -x -e 2029,2164,2086,2046,2068,2119,2033 "$@" || return $? - # had this before. not sure what it is 2119 + + + # disable a warning with: + # shellcheck disable=SC2206 # reasoning + + # see bash-template/style-guide.md for justifications + + local quotes others + quotes=2048,2068,2086,2206 + others=2029,2033,2054,2164 + shellcheck -W 999 -x -e $quotes,$others "$@" || return $? } @@ -1570,7 +1887,6 @@ sl() { return 1 fi - now=$(date +%s) dorsync=false haveinfo=false tmpa=($SL_INFO_DIR/???????????"$remote") @@ -1628,7 +1944,7 @@ sl() { RSYNC_RSH="ssh ${args[*]}" m rsync -rptL --delete $sl_rsync_args $SL_FILES_DIR "$remote": fi if $dorsync || ! $haveinfo; then - sshinfo=$SL_INFO_DIR/$now$type"$remote" + sshinfo=$SL_INFO_DIR/$EPOCHSECONDS$type"$remote" [[ -e $SL_INFO_DIR ]] || mkdir -p $SL_INFO_DIR printf "%s\n" "$extra_info" >$sshinfo chmod 666 $sshinfo @@ -1814,6 +2130,12 @@ psnetns() { if [[ $x ]]; then echo "$x"; else echo $l; fi; done } +nonet() { + if ! s ip netns list | grep -Fx nonet &>/dev/null; then + s ip netns add nonet + fi + sudo -E env /sbin/ip netns exec nonet sudo -E -u iank /bin/bash +} m() { printf "%s\n" "$*"; "$@"; } @@ -1864,25 +2186,7 @@ s/^\Wcapability: (.*)/\1/;Ta;h;b # * misc stuff -# temporary variables to test colorization -# some copied from gentoo /etc/bash/bashrc, -use_color=false -# dircolors --print-database uses its own built-in database -# instead of using /etc/DIR_COLORS. Try to use the external file -# first to take advantage of user additions. -safe_term=${TERM//[^[:alnum:]]/?} # sanitize TERM -match_lhs="" -[[ -f ~/.dir_colors ]] && match_lhs="${match_lhs}$(<~/.dir_colors)" -[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(/dev/null \ - && match_lhs=$(dircolors --print-database) -# test if our $TERM is in the TERM values in dircolor -[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true - - -if ${use_color} && [[ $- == *i* ]]; then - +if $use_color && type -p tput &>/dev/null; then term_bold="$(tput bold)" term_red="$(tput setaf 1)" term_green="$(tput setaf 2)" @@ -1894,7 +2198,6 @@ if ${use_color} && [[ $- == *i* ]]; then # term_underl="$(tput smul)" # term_blue="$(tput setaf 4)" # term_cyan="$(tput setaf 6)" - fi # Try to keep environment pollution down, EPA loves us. unset safe_term match_lhs use_color @@ -1904,6 +2207,16 @@ unset safe_term match_lhs use_color if [[ $- == *i* ]]; then + + case $HOSTNAME in + bk|je|li) + if [[ $EUID == 1000 ]]; then + system-status _ ||: + fi + ;; + esac + + # this needs to come before next ps1 stuff # this stuff needs bash 4, feb 2009, # old enough to no longer condition on $BASH_VERSION anymore @@ -1945,10 +2258,7 @@ if [[ $- == *i* ]]; then 0) ps_color="$term_purple" ps_char='\$' ;; - 1) ps_color="$term_green" - ps_char="$return \\$" - ;; - *) ps_color="$term_yellow" + *) ps_color="$term_green" ps_char="$return \\$" ;; esac @@ -1964,19 +2274,19 @@ if [[ $- == *i* ]]; then if [[ -e /dev/shm/iank-status && ! -e /tmp/quiet-status ]]; then eval $(< /dev/shm/iank-status) fi - if [[ ! $SSH_CLIENT && $MAIL_HOST != "$HOSTNAME" ]]; then + if [[ $MAIL_HOST && $MAIL_HOST != "$HOSTNAME" ]]; then ps_char="@ $ps_char" fi # We could test if sudo is active with sudo -nv # but then we get an email and log of lots of failed sudo commands. # We could turn those off, but seems better not to. if [[ $EUID != 0 ]] && [[ $DID_SUDO ]]; then - ps_char="SUDO $ps_char" + psudo="\[$term_bold$term_red\]s\[$term_nocolor\] " fi if [[ ! $HISTFILE ]]; then ps_char="NOHIST $ps_char" fi - PS1="${PS1%"${PS1#*[wW]}"} \[$ps_color\]$ps_char\[$term_nocolor\] " + PS1="${PS1%"${PS1#*[wW]}"} $psudo\[$ps_color\]$ps_char\[$term_nocolor\] " # set titlebar. instead, using more advanced # titelbar below