\x1B[38;5;105m and \x1B[38;5;141m are a great combo.
Python antipattern: Close in finally
Don’t do this:
thing = Thing() try: thing.do_stuff() finally: thing.close()
Do do this:
from contextlib import closing with closing(Thing()) as thing: thing.do_stuff()
Why is the second better? Using contextlib.closing() ties closing the item to its creation. These baby examples are about equally easy to reason about, with only a single line in the try block, but consider what happens ifwhen more lines get added in future? In the first example, the close moves away, potentially offscreen, but that doesn’t happen in the second.
Too many git branches?
Do you have too many git branches on the go at once? Here is the command to list them in order of last modification:
git for-each-ref --sort=-committerdate refs/heads
Python atomic counter
Do you need a thread-safe atomic counter in Python? Use itertools.count():
>>> from itertools import count >>> counter = count() >>> next(counter) 0 >>> next(counter) 1 >>> next(counter) 2
I found this in the decorator package, labelled Atomic get-and-increment provided by the GIL
. So simple! So cool!
git submodule forgetting
Did you forget the -r when cloning a git repo with submodules? The command you’re looking for is git submodule update --init
GitLab YAML Docker Registry client
Have you written a Docker Registry API client in GitLab CI/CD YAML? I have.
# Delete candidate image from CI repository. clean-image: stage: .post except: - main variables: AUTH_API: "$CI_SERVER_URL/jwt/auth" SCOPE: "repository:$CI_PROJECT_PATH" REGISTRY_API: "https://$CI_REGISTRY/v2/$CI_PROJECT_PATH" before_script: - > which jq >/dev/null || (sudo apt-get update && sudo apt-get -y install jq) script: - echo "Deleting $CANDIDATE_IMAGE" - > TOKEN=$(curl -s -u "$CI_REGISTRY_USER:$CI_REGISTRY_PASSWORD" "$AUTH_API?service=container_registry&scope=$SCOPE:delete,pull" | jq -r .token) - > DIGEST=$(curl -s -I -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "$REGISTRY_API/manifests/$CI_COMMIT_SHORT_SHA" | tr -d "\r" | grep -i "^docker-content-digest: " | sed "s/^[^:]*: *//") - > curl -s -X DELETE -H "Authorization: Bearer $TOKEN" "$REGISTRY_API/manifests/"$(echo $DIGEST | sed "s/:/%3A/g")
sudo tee >/dev/null
Need to redirect to a file from sudo? Use sudo tee >/dev/null:
$ sudo ls -l /root >/root/files.list -bash: /root/files.list: Permission denied $ sudo ls -l /root | sudo tee /root/files.list >/dev/null $ sudo ls -l /root/files.list -rw-r--r-- 1 root root 94 Oct 18 09:31 /root/files.list
Use stdbuf to tee without buffering
Do you want to tee the output of a command to a file, but see it in your terminal too, without buffering? The stdbuf command can do this for you:
$ sudo stdbuf --output=L tcpdump -i any -tttt -n 'udp port 5353' | tee -a tcpdump-mdns
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
2023-06-15 11:55:16.637670 eth0 M IP 10.0.0.23.5353 > 224.0.0.251.5353: 0 A (QM)? winnebago.local. (28)
2023-06-15 11:55:16.744660 eth0 M IP 10.0.0.42.5353 > 224.0.0.251.5353: 0*- [0q] 1/0/0 (Cache flush) A 10.0.0.42 (38)
...
Which uninstalled package provides a file?
$ apt-file find guestmount guestmount: /usr/bin/guestmount guestmount: /usr/share/bash-completion/completions/guestmount guestmount: /usr/share/doc/guestmount/changelog.Debian.gz guestmount: /usr/share/doc/guestmount/copyright guestmount: /usr/share/man/ja/man1/guestmount.1.gz guestmount: /usr/share/man/man1/guestmount.1.gz guestmount: /usr/share/man/uk/man1/guestmount.1.gz
Scripting DNS lookups
Are you writing a script and some command doesn’t accept hostnames and you don’t want to inline the IP address? dig +short is your friend!
$ dig +short gbenson.net 69.163.152.201