fi
# -q = quiet
journalctl -qn2 -f -u "$cmd_name" &
+ jr_pid=$!
# 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
- jr_pid=$!
systemd-run --unit "$cmd_name" --wait --collect "$cmd" "$@" || ret=$?
# The sleep lets the journal output its last line
# before the prompt comes up.
done
}
+screenrtp() {
+
+ local ip port xoffset
+ read -r ip port xoffset <<<"$@"
+
+ setxenv
+
+ if [[ ! $port ]]; then
+ port=9999
+ fi
+
+ while true; do
+ # By default, plugged in screen goes to the right side, so we need an
+ # offset that is the same as the laptop's x resolution. If we are in
+ # mirror mode, then we don't need an offset.
+ if [[ ! $xoffset ]]; then
+ xoffset=0
+ laptop_x=$(xrandr | awk '$1 == "LVDS-1" {print $4}' | sed 's/x.*//') || { sleep 1; continue; }
+ total_x=$(xdpyinfo| awk '$1 == "dimensions:" {print $2}' | sed 's/x.*//') || { sleep 1; continue; }
+ screen2_res=$(xrandr | awk '$2 == "connected" && $1 != "LVDS-1" { print $3 }' | sed 's/+.*//')
+ if (( laptop_x < total_x )); then
+ xoffset=$laptop_x
+ fi
+ fi
+
+ m ffmpeg -probesize 50M -thread_queue_size 50 \
+ -video_size $screen2_res -f x11grab -framerate 30 -i :0.0+$xoffset.0 \
+ -vcodec libx264 -g 1 -tune zerolatency -preset ultrafast -pix_fmt yuv420p -x264-params repeat-headers=1 \
+ -f rtp_mpegts rtp://$ip:$port ||:
+
+
+ sleep 1
+ done
+}
+
+setxenv() {
+ if [[ ! $DISPLAY ]]; then
+ export DISPLAY=:0.0
+ fi
+ if [[ ! $XAUTHORITY ]]; then
+ export XAUTHORITY=$HOME/.Xauthority
+ fi
+}
+
#### end fsf section
}
_khfix-common() {
- local host ip port file key tmp
- 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" ||: )
+ local host ip port file key tmp ssh_host alias
+ ssh_host=$1
+ {
+ read -r host ip port
+ read -r alias;
+ # note ":graph:" is needed or else we get a trailing \r out of ssh,
+ # dunno why. web search says terminals add \r, so I tried adding -T
+ # to turn off psuedo terminal, but it didnt help.
+ } < <(timeout -s 9 2 ssh -TN -oBatchMode=yes -oControlMaster=no -oControlPath=/ -v $ssh_host |&
+ sed -rn "s/debug1: Connecting to ([^ ]+) \[([^\]*)] port ([0-9]+).*/\1 \2 \3/p;
+s/^debug1: using hostkeyalias: ([[:graph:]]*).*/\1/p" ||: )
file=$(readlink -f ~/.ssh/known_hosts)
if [[ ! $ip ]]; then
echo "khfix: ssh failed"
return 1
fi
+ ip_entry=$ip
+ host_entry=$host
+ if [[ $alias ]]; then
+ host_entry="$alias"
+ fi
if [[ $port != 22 ]]; then
ip_entry="[$ip]:$port"
- host_entry="[$host]:$port"
- else
- ip_entry=$ip
- host_entry=$host
+ if [[ ! $alias ]]; then
+ host_entry="[$host]:$port"
+ fi
fi
- if [[ $host != "$ip" ]]; then
+ if [[ $host_entry != "$ip_entry" ]]; then
tmp=$(mktemp)
ssh-keygen -F "$host_entry" -f $file >$tmp || [[ $? == 1 ]] # 1 when it doesnt exist in the file
if [[ -s $tmp ]]; then
key=$(sed -r 's/^.*([^ ]+ +[^ ]+) *$/\1/' $tmp)
+ else
+ echo "khfix WARNING: did not find host entry:$host_entry in known_hosts"
fi
rm $tmp
if [[ $key ]]; then
ssh-keygen -F "$ip_entry" -f $file >$tmp || [[ $? == 1 ]]
if [[ -s $tmp ]]; then
key=$(sed -r 's/^.*([^ ]+ +[^ ]+) *$/\1/' $tmp)
+ else
+ echo "khfix WARNING: did not find ip entry:$ip_entry in known_hosts"
fi
rm $tmp
if [[ $key ]]; then
grep -Fv "$key" "$file" | sponge "$file"
fi
- ll ~/.ssh/known_hosts
}
khfix-r() { # known hosts fix without syncing to root user
_khfix-common "$@" || return 1
done
}
caf() {
-
local file
find -L "$@" -type f -not \( -name .svn -prune -o -name .git -prune \
-o -name .hg -prune -o -name .editor-backups -prune \
-o -name .undo-tree-history -prune \) -printf '%h\0%d\0%p\n' | sort -t '\0' -n \
| awk -F '\0' '{print $3}' 2>/dev/null | while read -r file; do
- hr
- printf "%s\n" "$file"
- hr
- cat "$file"
+ hr "$file"
+ v "$file"
done
}
ccomp cat cf caf
etail2() {
tail -F /var/log/exim4/mymain -n 200 "$@"
}
-ccomp tail etail etail2
+# shortcut
+ta() {
+ tail -F "$@"
+}
+ccomp tail etail etail2 ta
# ran into this online, trying it out
detach() {
sed -rn '/testignore|jtuttle|eximbackup/!s/^[^ ]+ ([^ ]+) [^ ]+ [^ ]+ <= ([^ ]+).* id=([^ ]+) T="(.*)" from (<[^ ]+> .*$)/\1 \5\n \3\n \4/p' <${1:-/var/log/exim4/mainlog}
}
etailin() {
- tail -F /var/log/exim4/mainlog | sed -rn '/testignore|jtuttle|eximbackup/!s/^[^ ]+ ([^ ]+) [^ ]+ [^ ]+ <= ([^ ]+).*T="(.*)" from (<[^ ]+> .*$)/\1 \4\n \3/p'
+ local -a tail_arg
+ tail_arg=(-n500)
+ if [[ $1 ]]; then
+ tail_arg=($@)
+ fi
+ tail "${tail_arg[@]}" -F /var/log/exim4/mainlog | sed -rn '/testignore|jtuttle|eximbackup/!s/^[^ ]+ ([^ ]+) [^ ]+ [^ ]+ <= ([^ ]+).*T="(.*)" from (<[^ ]+> .*$)/\1 \4\n \3/p'
}
done < <(find "$@" -print0);
}
+# shellcheck disable=SC2120
faf() { # find all files. use -L to follow symlinks
find "$@" -not \( -name .svn -prune -o -name .git -prune \
-o -name .hg -prune -o -name .editor-backups -prune \
args+=" -c"
fi
fi
- if [[ $EMACSDIR ]]; then
-
- # todo: we don't have to alter HOME since emacs 29+, we can set
- # user-emacs-directory with the flag --init-directory
-
- # Alter the path here, otherwise the nfs mount gets triggered on the
- # first path lookup when emacs is not being used.
- # shellcheck disable=SC2098 disable=SC2097 # false positive
- PATH="$EMACSDIR/lib-src:$EMACSDIR/src:$PATH" EHOME=$HOME HOME=$EMACSDIR m emacsclient -a "" $args "$@"
+ if $gdb; then
+ # due to a bug, we cant debug from the start unless we get a new gdb
+ # https://sourceware.org/bugzilla/show_bug.cgi?id=24454
+ # m gdb -ex="set follow-fork-mode child" -ex=r -ex=quit --args emacs --daemon
+ m emacsclient -a "" $args "$@"
+ sleep 1
+ cd "/a/opt/emacs-$(distro-name)$(distro-num)"
+ s gdb -p "$(pgrep -f 'emacs --daemon')" -ex c
+ cd -
else
- if $gdb; then
- # due to a bug, we cant debug from the start unless we get a new gdb
- # https://sourceware.org/bugzilla/show_bug.cgi?id=24454
- # m gdb -ex="set follow-fork-mode child" -ex=r -ex=quit --args emacs --daemon
- m emacsclient -a "" $args "$@"
- sleep 1
- cd "/a/opt/emacs-$(distro-name)$(distro-num)"
- s gdb -p "$(pgrep -f 'emacs --daemon')" -ex c
- cd -
- else
- m emacsclient -a "" $args "$@"
- fi
+ m emacsclient -a "" $args "$@"
fi
}
# horizontal row. used to break up output
hr() {
- local blocks
- # 180 is long enough.
- blocks=██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
- printf "%s\n" "$(tput setaf 5 2>/dev/null ||:)${blocks:0:${COLUMNS:-180}}$(tput sgr0 2>/dev/null||:)"
+ local start end end_count arg
+ # 180 is long enough. 5 for start.
+ start=█████ end=█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
+ end_count=$(( ${COLUMNS:-180} - 5 ))
+ arg="$*"
+ if [[ $arg ]]; then
+ end_count=$(( end_count - 2 - ${#arg} ))
+ start="$start $arg "
+ fi
+ if (( end_count >= 1 )); then
+ end=${end:0:$end_count}
+ else
+ end=
+ fi
+ printf "%s\n" "$(tput setaf 5 2>/dev/null ||:)$start$end$(tput sgr0 2>/dev/null||:)"
}
# highlight
hl() {
grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | uniq || [[ $? == 1 ]];
}
+# remove lines from history matching $1
+#
# 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.
/usr/bin/nagstamon &
}
-# profanity screen
+# profanity tmux
profsrc() {
- screen -RD -S profanity
+ screen -L profanity a
}
# i dont want to wait for konsole to exit...
fi
x=$(ps -eF)
# final grep is because some commands tend to have a lot of trailing spaces
- y=$(echo "$x" | grep -iP "$@" | grep -o '.*[^ ]') ||:
+ y=$(echo "$x" | sed -r 's,//[^[:space:]:@/]+:[^[:space:]:@/]+@,//REDACTED_URL_USER@PASS/,g' | grep -iP "$@" | grep -o '.*[^ ]') ||:
if [[ $y ]]; then
echo "$x" | head -n 1 || [[ $? == 141 ]]
echo "$y"
systemctl -n 40 status "$@"
}
+# assume last arg is a service and we want to tail its log.
+serj() {
+ local service jr_pid ret
+ ret=0
+ service="${*: -1}"
+ journalctl -qn2 -f -u "$service" &
+ sleep 3
+ s systemctl "$@" || ret=$?
+ sleep .5
+ kill %%
+ (( ret == 0 )) || return $ret
+}
+
seru() { systemctl --user "$@"; }
# like restart, but do nothing if its not already started
srestart() {
systemctl list-unit-files | rg "$@"
}
+# check whether we generally want to do sk on the file
+sk-p() {
+ [[ ! -L $f ]] && istext "$1" && [[ $(head -n1 "$1" 2>/dev/null) == '#!/bin/bash'* ]]
+}
sk() {
# see https://savannah.gnu.org/maintenance/fsf/bash-style-guide/ for justifications
local quotes others ret
quotes=2048,2068,2086,2206,2254
- others=2029,2032,2033,2054,2164,
- shellcheck -W 999 -x -e $quotes,$others "$@" || ret=$?
+ others=2029,2032,2033,2054,2164
+ shellcheck -x -W 999 -e $quotes,$others "$@" || ret=$?
if (( ret >= 1 )); then
echo "A template comment to disable is now in clipboard. eg: # shellcheck disable=SC2206 # reason"
cbs "# shellcheck disable=SC"
return $ret
fi
}
+
# sk with quotes. For checking scripts that we expect to take untrusted
# input in order to verify we quoted vars.
skq() {
shellcheck -W 999 -x -e $others "$@" || return $?
}
-# sk on all modified files in current git repo
+# sk on all modified & new files in current git repo. must git add for new files.
skmodified() {
local f
- for f in $(i s | awk '$1 == "modified:" {print $2}'); do
- if [[ ! -L $f ]] && istext "$f" && [[ $(head -n1 "$f" 2>/dev/null) == '#!/bin/bash'* ]]; then
+ for f in $(i s | awk '$1 == "modified:" {print $2}; $1 == "new" {print $3}'); do
+ if sk-p "$f"; then
sk $f ||:
fi
done
}
-# sk on all the files in current git repo (except those excluded)
+
+# sk on all the files in current git repo
skgit() {
- local f toplevel orig_dir tmp skip e
- local -a ls_files excludes
+ local f toplevel orig_dir tmp
+ local -a ls_files sk_files
toplevel=$(git rev-parse --show-toplevel)
if [[ $PWD != "$toplevel" ]]; then
orig_dir=$PWD
cd $toplevel
fi
- excludes=(
- 'disabled/*'
- # included from another file and checked there
- beet-data
- brc
- brc2
- )
- tmp=$(git ls-files)
+ # tracked & untracked files
+ tmp=$(git ls-files && git ls-files --others --exclude-standard)
mapfile -t ls_files <<<"$tmp"
for f in "${ls_files[@]}"; do
- skip=false
- for e in "${excludes[@]}"; do
- if [[ $f == $e ]]; then
- skip=true
- break
- fi
- done
- if $skip; then continue; fi
-
- if istext "$f" && [[ $(head -n1 "$f" 2>/dev/null) == '#!/bin/bash'* ]]; then
- sk $f ||:
+ if sk-p "$f"; then
+ sk_files+=("$f")
fi
done
+ sk "${sk_files[@]}"
if [[ $orig_dir ]]; then
cd $orig_dir
fi
slr() {
sl --rsync "$@"
}
-sss() { # ssh solo
- sl -oControlMaster=no -oControlPath=/ "$@"
+
+
+# ssh solo
+#
+# WARNING: If you are trying to use -i, remember that keys added to
+# agent previously will still be tried. Use ssh-add -D to remove all
+# keys from the agent.
+sss() {
+ ssh -oControlMaster=no -oControlPath=/ "$@"
}
# kill off old shared socket then ssh
ssk() {
for n in $numbers
do
- _spark_echo -n ${ticks[$(( (((n-min)<<8)/f) ))]}
+ _spark_echo -n ${ticks[$(( ((n-min)<<8)/f ))]}
done
_spark_echo
}
}
catnew() {
- local dir file
+ local dir file _
dir="$1"
+ # shellcheck disable=SC2030
inotifywait -m "$dir" -e create -e moved_to | while read -r _ _ file; do
hr
cat "$dir/$file"
if [[ $HISTFILE ]]; then
history -a # save history
+ if [[ -e $HOME/.iank-stream-on ]]; then
+ if [[ $HISTFILE == $HOME/.bh ]]; then
+ ps_char="HISTP "
+ fi
+ elif [[ $HISTFILE == /a/bin/data/stream_hist ]]; then
+ ps_char="HISTS "
+ fi
fi
ps_color="$term_purple"
- ps_char='\$'
+ ps_char="$ps_char"'\$'
if [[ ! -O . ]]; then # not owner
if [[ -w . ]]; then # writable
ps_color="$term_bold$term_red"
fi
jobs_char=
if [[ $(jobs -p) ]]; then
- jobs_char='j\j '
+ jobs_char="$(jobs -p)"'j\j '
fi
fi
+
+lp22viewers() {
+ v=0
+ roomv=(0 0)
+ rooms=(jupiter saturn)
+ for ip in 209.51.188.25 live.fsf.org; do
+ out=$(curl -sS --insecure https://$ip/)
+ for i in 0 1 2; do
+ room=${rooms[i]}
+ while read -r n; do
+ v=$((v+n))
+ # shellcheck disable=SC2004 # false positive
+ roomv[$i]=$(( ${roomv[$i]} + n ))
+ done < <(printf "%s\n" "$out" | grep -Po "$room.*?current[^0-9]*[0-9]*" | grep -o '[0-9]*$' )
+ done
+ done
+ printf "total: %s " $v
+ for i in 0 1; do
+ room=${rooms[i]}
+ printf "$room: %s " "${roomv[$i]}"
+ done
+ echo
+}
+
+arpflush() {
+ local default_route_dev
+ default_route_dev=$(ip r show default | sed 's/.*dev \([^ ]*\).*/\1/' | head -n1)
+ m s ip n flush dev "$default_route_dev"
+}
+
+dsh() {
+ command dsh -c "$@"
+}
+
+# cat or bat with color if we have it
+v() {
+ if type -t batcat >/dev/null; then
+ # note: another useful useful style is "header"
+ batcat --color always --style plain --theme Coldark-Cold -P "$@"
+ else
+ cat "$@"
+ fi
+}
+
# * stuff that makes sense to be at the end