Contact
Christopher Bock <christopher@bocki.com>
cb on irc.oftc.net
crpb on irc.libera.chat
some of my shell functions / aliases
1 alias envi='env -i HOME=$HOME TERM=$TERM PATH=$(getconf PATH)'
2 alias patterns='man 7 apt-patterns |\grep --colour -E "(~|\?)[a-Z]+"'
3 alias debian_pin_helper='apt-cache policy| sed "s/o=/\n\tORIGIN=/g;s/a=/\n\tARCHIVE=/g;s/n=/\n\tCODENAME=/g;s/v=/\n\tVERSION=/g;s/l=/\n\tLABEL=/g;s/c=/\n\tCOMPONENT=/g;s/b=/\n\tARCHITECTURE=/g"'
4 alias debian_release='wget -O- -q http://deb.debian.org/debian/dists/stable/Release |awk "/^(Suite|Codename|Version|Description):/" |paste - - - -'
5 alias debian_releases='wget -O- -q http://deb.debian.org/debian/dists/{oldoldstable,oldstable,stable,testing,unstable,experimental}/Release |awk "/^(Suite|Codename|Description):/" |paste - - - |expand -t 20'
6 alias debian_channels='curl -s https://wiki.debian.org/IRC |grep -Po "(?<=>)#.*?(?=<)" |sort |uniq'
7 alias diff='diff --color --exclude=".git" --exclude="__pycache__"'
8 alias glog='git log --graph --decorate=full --name-status'
9 alias glogf='git log --graph --decorate=full --follow -p'
10 alias gloga='git log --graph --decorate=full --name-status --all ^'
11 alias trente-ente='t=~/.RHABARBERBARBARA; rm -f $t; ssh-keygen -t ed25519 -P "" -f $t >/dev/null; cat $t.pub |xsel -b ; cat $t |xsel -p ; rm -f $t $t.pub'
12 alias secbash='systemd-run --pty --property=DynamicUser=yes /bin/bash --norc'
13 alias seczsh='systemd-run --pty --property=DynamicUser=yes /bin/zsh --no-rcs'
14
15
16 # print apt_log w/o so much clutter
17 apt_hist() {
18 #test -z $(dpkg --print-foreign-architectures) && DELARCH=":$(dpkg --print-architecture)" || DELARCH="RHABARBER" # Only show arch on multiarch system
19 DELARCH=":$(dpkg --print-architecture)"
20 awk '!/^End|^Error:/ { gsub( /\([^()]*\)/ ,"" );
21 gsub(/ ,/,""); gsub(/^(Commandline|Start-Date): /,"");
22 sub(/^Install: /,""); print}' <(zcat -f -- $(find /var/log/apt/history.log* |tac) 2>/dev/null) |sed "s#$DELARCH##g"
23 #print}' <(zcat -f -- $(find /var/log/apt/history.log* |sort -rV) 2>/dev/null) |sed "s#$DELARCH##g" #alternativ
24 }
25
26 # get screenshot url's for package*
27 dscreenshot() {
28 {
29 for package in "$@"; do
30 printf '\thttps://screenshots.debian.net/package/%s\n' "$package"
31 command psql "postgresql://udd-mirror:udd-mirror@udd-mirror.debian.net/udd" -qAt -F $'\t' --command="select package,version,large_image_url from screenshots where package LIKE '"$package"' ORDER BY version ASC"
32 done
33 }
34 }
35 compdef '_deb_packages avail' dscreenshot
36
37 apt_show_source() {
38 {
39 apt show ${1:-*} |& sed '1,3d' |awk '/^(Package|APT-Sources): / {$1=""; print $NFR}' |sed 'N;s/\n/\t/' |expand -t $(( $COLUMNS / 3 ))
40 }
41 }
42 compdef '_deb_packages avail' apt_show_source
43
44 apt_show_maintainer() {
45 apt show "${1:-*}" |& sed '1,3d' |awk '/^(Package|Maintainer): / {$1=""; print $NFR}' |sed 'N;s/\n/\t/' |expand -t $(( $COLUMNS / 3 ))
46 }
47 compdef '_deb_packages avail' apt_show_maintainer
48
49 # show estimated disk-usage of all installed packages
50 dpkg_installedsize() {
51 dpkg-query -Wf '${Installed-Size}\n' | \
52 awk '{ sum += $1 } END { print sum/1024" MB" }'
53 }
54
55 # Get latest netinst.iso
56 debian_download_netinst() {
57 (
58 ARCH="${1:-amd64}"
59 URL="https://cdimage.debian.org/debian-cd/current/$ARCH/iso-cd"
60 DEBTMP=
61 DEBTMP="$(command mktemp --suffix=debiancd -d)"
62 command gpg --keyserver keyring.debian.org --recv-keys 64E6EA7D 6294BE9B 09EA8AC3
63 cd $DEBTMP || return 1
64 command wget -P $DEBTMP $URL/SHA512SUMS{,.sign} || return 1
65 ISO="$(command awk '/debian-[0-9.]*-'$ARCH'-netinst.iso$/ {print $2}' $DEBTMP/SHA512SUMS)"
66 printf "\n\v\tThe current ISO is %s\n\v\tEnter for yes, Ctrl-c for no\v" $ISO
67 read accept
68 command wget -P $DEBTMP $URL/$ISO || return 1
69 command gpg --with-fingerprint --verify $DEBTMP/SHA512SUMS.sign || return 1
70 command shasum --ignore-missing --check $DEBTMP/SHA512SUMS || return 1
71 command printf "Finished download:\n\v\t%s\v\n" $DEBTMP/$ISO
72 )
73 }
74
75 # deb822 formated .sources
76 deb822() {
77 local list # sources
78 if [ -t 0 ]; then
79 list="$(cat ${1:-/usr/share/doc/apt/examples/sources.list})"
80 else
81 list="$(cat /dev/stdin)"
82 fi
83 # sources="$(dirname $list)/$(basename $list |sed 's/\.list/\.sources/')"
84 echo $list | sed -e 's/\[.*\]//g' -e 's/^[\t ]*//g' | \
85 awk '/^deb/ {
86 printf "Types: "$1"\nURIs: "$2"\nSuites: "$3"\nComponents: "; $1=$2=$3="";
87 sub(/^[ \t]+/, ""); printf $0"\nEnabled: yes\n#Signed-By: \n\n"}' # | sudo tee -a $sources
88 # sudo mv $list $list.bak
89 }
90
91 # deb822 print sources
92 deb822_list() {
93 for f in $(echo /etc/apt/sources.list.d/*${1}*.sources); do
94 printf "${f}\n%80s\n" |tr " " "#"
95 cat "${f}"
96 done
97 }
98
99
100 # Size of all Packages Installed
101 dpkg_installedsize() {
102 dpkg-query -Wf '${Installed-Size}\n' | \
103 awk '{ sum += $1 } END { print sum/1024" MB" }'
104 }
105
106 archive_lookup() {
107 command -v jq curl >/dev/null || return 1
108 local URL RET D
109 URL="$1"
110 #RET=( $(curl "http://archive.org/wayback/available?url=$(urldecode "$URL")" |jq -r '.archived_snapshots?|.closest.timestamp,.closest.url'))
111 for timestamp in 19700000000 20991231235959; do
112 RET=( $(curl "http://archive.org/wayback/available?timestamp=${timestamp}&url=${URL}" |jq -r '.archived_snapshots?|.closest.timestamp,.closest.url'))
113 D=${RET[1]}
114 if ! [ $D = null ]; then
115 D="${D::4}-${D:4:2}-${D:6:2}T${D:8:2}:${D:10:2}+${D:12:2}:00"
116 printf 'Date: %s URL: %s\n' "$D" "${RET[2]}"
117 fi
118 done
119 }
120
121 pastebin() {
122 { if [ -t 0 ]; then
123 cat $1
124 else
125 cat /dev/stdin
126 fi } | command -p pastebinit |sed 's%/hidden/%/plainh/%'| tee >(tr -d "\n"| xclip -i -selection clipboard) |tee -a ~/.pastebinit_history
127 # local archive...
128 local URL PASTEID
129 URL="$(xclip -selection clipboard -o |sed 's/\/$//g')"
130 PASTEID=${URL##*/}
131 wget --quiet "$(xclip -selection clipboard -o |sed 's/\/$//g')" --output-document="$HOME/.pastebinit_history.d/$PASTEID"
132 }
133
134 # PASTE LATEST SCREENSHOT
135 0x0() {
136 local file img url ttl=96 histfile=~/.0x0_history res dir=~/snips
137 if [ "$1" = "-h" ]; then
138 cat << EOF
139 Usage: arg[1] = filename or nothing for newest file in $dir
140 -h for help
141 -f for fuzzy thingy
142 -d for printing curl statements for all tokens
143 EOF
144 elif [ "$1" = "-f" ]; then
145 awk 'NF>2' $histfile |
146 fzf --disabled \
147 --bind="p:execute:sensible-browser {2}" \
148 --bind 'd:preview:command curl -s -Fdelete= -Ftoken="{3}" {2}' \
149 --preview-window=up \
150 --header "p: sensible-browser URL; d: delete on 0x0; return: print curl to cli in background" \
151 --bind 'enter:execute:echo curl -Fdelete= -Ftoken="{3}" {2}'
152 elif [ "$1" = "-d" ]; then
153 awk '{printf "curl -Ftoken=%s -Fdelete= %s\n", $3, $2}' $histfile
154 else
155 file="$(print "$dir"/*(.om[1]))"
156 img="${1-$file}"
157 # '${${img}:a:q}' only works with zsh. you will need an alternative in bash
158 printf '%s\nfile://%s\nPress Enter to upload! ' ${${img}:a:q} ${${img}:a:q}
159 # printf 'file://%s\n' ${${img}:a:q}
160 read accept
161 # curl -s -F"file=@${img}" -Fexpires=96 -Fsecret= https://0x0.st | \
162 # tee >(tr -d '\n'| xsel -i -b)
163 res=( $(curl --write-out '%header{x-token}' -s -F"file=@${img}" -Fexpires=$ttl -Fsecret= https://0x0.st) )
164 printf '%s' "${res[1]}" | xsel -i -b
165 printf '%s\t%s\t%s\t%s\n' "$(date -Im)" "${res[1]}" "${res[2]}" "${file}" |tee -a "${histfile}"
166 fi
167 }
168
169 # Fluxbox apps helper
170 fbxprop() {
171 printf '[app] %s \n[end]\n' "$(
172 xprop WM_CLASS WM_NAME WM_WINDOW_ROLE |
173 sed 's/WM_\(.*\)(\(.*\)) = "//g;s/", "/\n/;s/"$//'|
174 sed '1 s/^/(name=/;2 s/^/(class=/;3 s/^/(title=/;4 s/^/(role=/;s/$/)/g' |
175 # WM_WINDOW_ROLE might not be found
176 grep -v WM_WINDOW_ROLE |tr '\n' ' ')"
177 }
178
179
180 tmux_cssh() {
181 local split match name hosts OPTS
182 if test $# -ge 3 ; then
183 if [[ $3 =~ ^[0-9]+$ ]]; then
184 split="$3"
185 fi
186 fi
187 if test $# -ge 2 ; then
188 match="$1"
189 if [[ $2 =~ ^[0-9]+$ ]] && [[ $# = 2 ]]; then
190 split="$2"
191 name="$(tr -cd '[:alnum:]' <<< "$1")"
192 else
193 name="$2"
194 fi
195 fi
196 if test $# = 1 ; then
197 if test -z "$(tr -d '[:alnum:]' <<< "$1")"; then
198 match="$1."
199 name="$1"
200 else
201 match="$1"
202 name="$(tr -cd '[:alnum:]' <<< "$1")"
203 fi
204 fi
205 if test $# = 0 ; then
206 return 0
207 fi
208 OPTS=(-ts "${name}" -sa -A)
209 if ! test -z $split ; then OPTS=(${OPTS[@]} -sw "$split"); fi
210 echo tmux-cssh ${OPTS[@]} $(awk '/^Host .*('$match').*$/ {printf "%s ", $2}' ~/git/ssh_config/*.ssh ~/.ssh/config)
211 tmux-cssh "${OPTS[@]}" $(awk '/^Host .*('$match').*$/ {printf "%s ", $2}' ~/git/ssh_config/*.ssh ~/.ssh/config)
212 }
213
214 _cows() {
215 ( command -v cowsay lolcat faketime || sudo apt install --yes cowsay lolcat faketime ) >/dev/null 2>&1
216 OPTS=( -b -d -g -n -p -s -t -w -y ); for opt in ${OPTS[@]}; do echo "${1:=MUUUH}" |cowsay $opt |lolcat ; done
217 for tach in 12-25 08-16 11-07 02-18 04-01; do faketime 2022-$tach apt-get moo| lolcat; done
218 apt-get -o APT::Moo::Color=true moo moo
219 }
220
221 # QEMU RUN ISO
222 qemu_iso() {
223 iso="$1"
224 shift
225 qemu-system-x86_64 --enable-kvm --smp 4 -boot d -m 2G \
226 -nic user,ipv6=off,model=vmxnet3 --display gtk --serial stdio \
227 -cdrom "$iso" $@
228 }
229 qemu_serial() {
230 iso="$1"
231 shift
232 qemu-system-x86_64 --enable-kvm --smp 4 -boot d -m 2G \
233 -nic user,ipv6=off,model=vmxnet3 --display curses --nographic --vga none \
234 -cdrom "$iso" $@
235 }
236
237 gdiff() {
238 local N
239 test "$1" -eq "$1" && N="$1" || N=1
240 git diff HEAD~${N} HEAD
241 }
242 gdiffs() {
243 git diff --staged
244 }
245
246 # clone git repo to e.g. ~/git/$sitename/$usercorpname/$reponame
247 gclone() {
248 {
249 if ((DEBUGTHIS)); then set -x; fi
250 testuri() { git ls-remote --quiet $1 HEAD >/dev/null 2>&1 ; }
251 local base url prot link domain subpath usr notld repo rpath
252 base=~/git/
253 url="$1"
254 if ! testuri "$url"; then
255 echo "Couldn't find a git repository at ${url}!" >/dev/stderr
256 return 65
257 fi
258 if [[ "$url" =~ "https?://" ]]; then
259 prot="${url%:*}"
260 link="${url#${prot}://}"
261 domain="${link%%/*}"
262 subpath="${link#${domain}}"
263 elif [[ "$url" =~ "^git@" ]]; then
264 prot="${url%@*}"
265 link="${url#${prot}@}"
266 domain="${link%%:*}"
267 subpath="${link#${domain}:}"
268 fi
269 usr="${subpath%/*}"
270 notld="${domain%.*}"; notld="${notld#git.}"
271 repo="${link##*/}"; repo="${repo%*.git}"
272 rpath="$(realpath -sm "$base/$notld/$usr/$repo"|tr '[:upper:]' '[:lower:]')"
273 if [ -n "$ZSH_VERSION" ] && type zstyle >/dev/null 2>&1; then
274 vared -p "Clone $url to: " rpath
275 elif [ -n "$BASH_VERSION" ] && type caller >/dev/null 2>&1; then
276 rpath="$(read -e -r -p "Clone "$url" to: " -i "$rpath"; echo "$REPLY")"
277 fi
278 if ! test -d "$rpath"; then
279 mkdir -p "${rpath%/*}"
280 git clone "$url" "$rpath"
281 cd $_
282 else
283 printf 'Directory %s already exists!\n' "$rpath"
284 cd $_
285 fi
286 set +x
287 }
288 }
289
290
291
292
293
294 # libvirt shrink all qcow images
295 libvirt_shrink_qcow() {
296 VMSR=( $(virsh --quiet --connect=qemu:///session list --state-running --name) )
297 VMS=( $(virsh --quiet --connect=qemu:///session list --all --name) )
298 for VM in "${VMSR[@]}"; do
299 printf "Stopping VM: $VM\n"
300 virsh --quiet --connect=qemu:///session shutdown --domain $VM
301 sleep 0.5
302 done
303 while true; do
304 if [[ -z $(virsh --quiet --connect=qemu:///session list --state-running --name) ]]; then
305 break
306 else
307 printf "VMs still running: %s\n" "$(virsh --quiet --connect=qemu:///session list --state-running --name |tr '\n' ' ')"
308 printf "Waiting 5 seconds to check again\n"
309 sleep 5
310 fi
311 done
312 printf "\n"
313 for VM in "${VMS[@]}"; do
314 printf "VM: $VM\n"
315 for IMG in $(virsh --quiet --connect=qemu:///session domblklist --details --domain $VM | awk '/disk.*qcow2$/{print $NF}'); do
316 printf "Compressing $IMG\n"
317 time qemu-img convert -p -c -O qcow2 $IMG $IMG.tmp
318 mv -v $IMG{,.bak}
319 mv -v $IMG{.tmp,}
320 ls -1sh ${IMG}*
321 printf "\n"
322 BAKS="${BAKS} ${IMG}.bak"
323 done
324 done
325 for VM in $VMSR; do
326 printf "Starting VM: $VM\n"
327 virsh --quiet --connect=qemu:///session start --domain $VM;
328 done
329 printf "\nDon't forget to cleanup the backups:\n rm %s \n" $BAKS
330 }
331
332
333 # libvirt snapshot overview
334 virsnaps() {
335 local DOMS DOM SNAPS TREE CURRENT
336 local SES=${1:-session}
337 DOMS=( $(virsh --quiet --connect=qemu:///${SES} list --all --name) )
338 echo -e "\033[1mDomains: ${DOMS[@]}\033[0m"
339 for DOM in ${DOMS[@]}; do
340 CURRENT="$(virsh --quiet --connect=qemu:///${SES} snapshot-current --name --domain "$DOM" 2>/dev/null)"
341 SNAPS="$(virsh --connect=qemu:///${SES} snapshot-list --topological --parent --domain "$DOM")"
342 TREE="$(virsh --connect=qemu:///${SES} snapshot-list --topological --tree --domain "$DOM")"
343 if [ "${#CURRENT}" -gt 0 ] ; then
344 printf '\033[1mDomain: %s\033[0m\n' "$DOM"
345 printf '%s\n' "$SNAPS"|sed ''/$CURRENT/s//$(printf "\033[1m$CURRENT\033[0m")/''
346 printf 'Tree:\033[0m\n%s\n' "$TREE"|sed ''/$CURRENT/s//$(printf "\033[1m$CURRENT\033[0m")/''
347 fi
348 done
349 }