Skip to content

Shell

Basic loop to iterate over lines in a file

Section titled “Basic loop to iterate over lines in a file”
Terminal window
for pkg in $(cat pkgs.txt); do sudo apt purge "$pkg" -y; done

More complex loop using ‘if’ statement

Section titled “More complex loop using ‘if’ statement”

Useful for control actions, cleaning up output, etc.

Terminal window
for node in $(cat nodes.txt); do \
echo "Node: ${node}"; \
ssh -q -t "$node" 'if [[ $(lsblk | grep -i lvm) ]]; then sudo apt install mdadm -y; fi'; \
done

Checking busy log files for their contents

Section titled “Checking busy log files for their contents”

This does not hang your console as opposed to using tail -f.

Terminal window
watch -n 0.5 sudo tail /var/log/named/queries.log

Declare nodes variable separately or prepend to loop and separate with semicolon.

Terminal window
for node in "${nodes[@]}"; do \
ping -c 2 -W 0.1 "$node" > /dev/null && \
echo "OK: ${node}" || echo "NOT OK: ${node}"; \
done

‘while’ loop to iterate over lines in a file

Section titled “‘while’ loop to iterate over lines in a file”

Avoids calls to cat as is the case with the for loop example. Using madison command rather than policy seems to be slightly faster.

Terminal window
while read pkg; do \
if [[ $(apt-cache madison "$pkg") ]]; then \
echo "OK: ${pkg} exists in some repo"; \
else \
echo "NOT OK: ${pkg} doesn't exist in any repo"; \
fi; \
done < pkgs.txt
Terminal window
types=($(grep -oE 'pattern' input.txt))
Terminal window
sed -n '/pattern1/,/pattern2/p' input.txt
Terminal window
stat -c '%a' /etc/passwd
Terminal window
last_character=${string_variable:-1}
Terminal window
grep -rl '\-\- MARK \-\-' /var/log/* | \
while read line; do \
echo "Working with file '${line}'"; \
grep MARK "$line" | tail -n1; \
done

Include lines before/after a ‘grep’ match

Section titled “Include lines before/after a ‘grep’ match”
Terminal window
grep -B 3 -A 3 -i "hv_fcopy" /var/log/messages

Find all unique directories in listed directories that contain files modified 10 minutes ago since the command was ran

Section titled “Find all unique directories in listed directories that contain files modified 10 minutes ago since the command was ran”
Terminal window
ls | xargs -I {} find {} -type f -mmin -10 | cut -d "/" -f2 | sort -u

Find all files in the current directories that were modified at least a minute ago, are larger than 500MB, and long list them

Section titled “Find all files in the current directories that were modified at least a minute ago, are larger than 500MB, and long list them”
Terminal window
find . -type f -mmin -1 -size +500M -exec ls -lsh {} \;

Find all files in the current directories that were modified at least a day ago, are larger than 2GB, and empty their contents

Section titled “Find all files in the current directories that were modified at least a day ago, are larger than 2GB, and empty their contents”
Terminal window
find . -type f -mtime -1 -size +2G -exec bash -c 'echo > {}' \;
Terminal window
ls | xargs -I {} git -C {} pull

Move ahead with Enter key.

Terminal window
set -x
trap read debug
Terminal window
dpkg-reconfigure tzdata
Terminal window
grep -ai "end:" /var/log/syslog
Terminal window
strace -c ls test/
Terminal window
echo "DEBUG: ${LINENO}"
Terminal window
awk '!visited[$0]++' your_file > deduplicated_file
Terminal window
ssh -q <username>@<endpoint> "sudo bash -s" < local_script.sh
Terminal window
mkdir new_directory && cd $_
Terminal window
$_
!$
Alt + .
!:1
!:1-2

From here.

Terminal window
ssh-keygen -lf ~/.ssh/id_rsa.pub
Terminal window
find . -xtype l
Terminal window
find . -lname '<relative-to-source target>*' \
-exec sh -c 'ln -sfn "<new relative-to-source target>/$(basename $0)" $0' {} \;
Terminal window
ssh -q <username>@<endpoint> './location/to/script'

The -l doesn’t truncate long names and hyphens with underscores aren’t replaced using -iso-level 4.

Terminal window
genisoimage -o data.iso -iso-level 4 -R -l data/
Terminal window
isoinfo -l -i data.iso

Works for both static and running output.

Terminal window
cat test.log | perl -pe 's/^\[\*\].*/\e[0;36m$&\e[0m/g; s/^\[\+\].*/\e[0;32m$&\e[0m/g; s/^\[\!\].*/\e[0;31m$&\e[0m/g'

From here.

For situations like these.

Terminal window
export PYTHONWARNINGS='ignore'
Terminal window
$ string='my_underscored_string_12345'
$ echo "$string" | rev | cut -d '_' -f 2- | rev
my_underscored_string
Terminal window
$ halt -p
REALLY!? -p
$ alias halt
alias halt='echo "REALLY!?"'
$ \halt -p
Connection to example.com closed by remote host.
Terminal window
function pretty_csv {
perl -pe 's/((?<=,)|(?<=^)),/ ,/g;' "$@" | column -t -s, | less -F -S -X -K
}
pretty_csv data.csv
pretty_csv < data.csv
sort data.csv | pretty_csv

From here

Terminal window
function pretty_tsv {
perl -pe 's/((?<=\t)|(?<=^))\t/ \t/g;' "$@" | column -t -s $'\t' | less -F -S -X -K
}
pretty_tsv data.tsv
pretty_tsv < data.tsv
sort data.tsv | pretty_tsv
Terminal window
diff -u file1 file2 > files.diff
Terminal window
$ cat /etc/cloud/build.info
build_name: server
serial: 20201211.1

Show top disk usage and exclude directories

Section titled “Show top disk usage and exclude directories”
Terminal window
du -Sh / --exclude=/{proc,sys,dev,var} | sort -rh | head -n 10
Terminal window
while :; do "looping"; done
Terminal window
exec /bin/bash

This provides access to more information.

Terminal window
$(which time) --verbose echo "test"

From here.

Also provides additional useful measurements.

Terminal window
perf stat --null --repeat 5 --table echo "test"

More examples here.

.parameters.vmObjects.value |= map(if .vmName == "router" then .moduleSnapshot = "fixed" else . end)

Use indirect references for dynamic variables

Section titled “Use indirect references for dynamic variables”
Terminal window
for host in "${hosts[@]}"; do
declare "parent_disk_${host}=$parent_disk"
done
for host in "${hosts[@]}"; do
parent_disk="parent_disk_${host}"
echo "${!parent_disk}"
done
Terminal window
msgcat --color=test
Terminal window
find . -type f -name '<file name>' -execdir mv {} "description.txt" \;
Terminal window
echo "text" | base64 -w 0
Terminal window
awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' combined.pem
Terminal window
echo "something" | install -D /dev/stdin directory/file.txt
Terminal window
find /the/dir/to/start/in -type f -mtime +365 -ls -exec rm -f -- {} \;
  • -p: permissions
  • -u: username/userid
  • -f: full path
  • -i: don’t print indentation lines
  • -d: print directories only
Terminal window
tree -pufid
Terminal window
pip freeze | grep "azure*" | xargs -n 1 pip uninstall -y
Terminal window
dnf history list <package>
Terminal window
dnf history info <transaction ID>

More on ‘history’

Terminal window
dnf history undo last
Terminal window
systemctl list-timers
Terminal window
journalctl -u name.timer
journalctl -u name.service
Terminal window
rsync -azvhP <user>@<remote>:<remote path> <local path>
Terminal window
rsync -av --delete ~/new/ ~/old
Terminal window
$ sudo dnf list --installed kernel-core* | tail -n +2 | wc -l
9

This goes in /etc/dnf/dnf.conf.

...
installonly_limit=10
...
Terminal window
$ sudo dnf install python3-dnf-plugins-extras-versionlock
$ # List kernel packages
$ rpm -qa kernel
kernel-6.0.18-300.fc37.x86_64
kernel-6.1.7-200.fc37.x86_64
kernel-6.1.8-200.fc37.x86_64
$ Add pin
$ sudo dnf versionlock add kernel-6.0.18-300.fc37.x86_64
Last metadata expiration check: 3:51:11 ago on E 30 jaan 2023 15:47:21.
Adding versionlock on: kernel-0:6.0.18-300.fc37.*
$ # Remove pin
$ sudo dnf versionlock delete kernel-6.0.18-300.fc37.x86_64
...

For example systemd-resolved.

Terminal window
$ systemctl revert systemd-resolved.service
Removed "/etc/systemd/system/systemd-resolved.service.d/override.conf".
Removed "/etc/systemd/system/systemd-resolved.service.d".
$ systemctl restart systemd-resolved.service

Equivalent to cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.

Terminal window
cp /etc/ssh/sshd_config{,.bak}

The same can be applied to directories:

Terminal window
cp -aR public{,.bak}

More on brace expansion.

Equivalent to cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config.

Terminal window
cp /etc/ssh/sshd_config{.bak,}
Terminal window
koji download-build --arch=x86_64 <kernel package name>

Fedora Discussion here.

Terminal window
readarray -t items < items.txt
parallel -kj 20 echo {1} ::: "${items[@]}"
Terminal window
openssl s_client -connect google.com:443 2> /dev/null | openssl x509 -noout -dates

This will leverage SystemD’s features.

Terminal window
$ systemd-run env
Running as unit: run-19945.service
$ journalctl -u run-19945.service
Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env...
Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env.
Sep 08 07:37:21 bupkis env[19948]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Sep 08 07:37:21 bupkis env[19948]: LANG=en_US.UTF-8
Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20.x86_64

Documentation here.

  1. Start a session: screen
  2. Start any long-running commands
  3. Detach from session: Ctrl+A+D
  4. List sessions: screen -ls
  5. Attach to a running session: screen -r <session ID>

Don’t send anything identifiable over SSH

Section titled “Don’t send anything identifiable over SSH”
Terminal window
ssh -a -i /dev/null -o IdentityAgent=/dev/null whoami.filippo.io
  • Ctrl + a: move to the beginning of the line
  • Ctrl + d: if you’ve type something, it deletes the character under the cursor, otherwise it quits the current shell
  • Ctrl + e: move to the end of the line
  • Ctrl + k: delete all text from the cursor to the end of the line
  • Ctrl + l: equivalent to clear
  • Ctrl + p: same as Up arrow
  • Ctrl + n: same as Down arrow
  • Ctrl + s: to stop output to terminal
  • Ctrl + q: to resume output to terminal after Ctrl + s
  • Ctrl + r: begins a backward search through command history, keep pressing to continue moving backwards
  • Ctrl + t: transpose the character before the cursor with the one under the cursor
    • Esc + t: transposes the two words before the cursor
  • Ctrl + u: cut the line before the cursor
    • Ctrl + y to paste it
  • Ctrl + w: cut the word before the cursor
    • Ctrl + y to paste it
  • Ctrl + x + Backspace: delete all text from the beginning of line to the cursor
  • Ctrl + x + Ctrl + e: launch editor defined by $EDITOR to input your command
    • exit the editor (e.g. wq) and the command will be ran automatically
    • useful for multi-line commands
  • Ctrl + z: stop current running process and keep it in background
    • fg to continue the process in the foreground
    • bg to continue the process in the background
  • Ctrl + _: undo typing

From here.

The ampersand means that the entirety of what was matched will be used in the replacement.

Terminal window
sed 's/create/&-repo/' input.txt