thebrowndomain
← All posts

Linux Tips & Tricks

· updated April 19, 2026
Linuxcommand-linenetworkingsshsystemd

A place for small but useful Linux command-line statements that have helped me lately. This blog isn’t really for you — it’s for me. A learning repository. But if any of it helps you, great.

Packages & ISOs

Extracting an RPM without installing it

Useful for peeking inside a package, grabbing one file out of it, or unpacking it onto a system that doesn’t use RPM.

rpm2cpio ./package.rpm | cpio -idmv

Debian equivalent:

dpkg-deb -x ./package.deb ./extracted/

Rebuilding a custom CentOS installation ISO

When building a custom CentOS installation disk, I use a kickstart file to automate the installation responses — you can define virtually every installation parameter, enabling fully automated deployment without manual intervention.

After dropping in the kickstart and any other tweaks, rebuild the ISO with:

genisoimage -u -r -v -T -J -joliet-long \
  -b isolinux/isolinux.bin -c isolinux/boot.cat \
  -no-emul-boot -boot-load-size 4 -boot-info-table \
  -eltorito-alt-boot -e images/efiboot.img \
  -o ../new.iso .

Networking

Who’s listening on that port?

netstat is deprecated on modern distros. ss is faster and comes with iproute2.

# TCP listeners with process names
sudo ss -ltnp

# Everything on a specific port
sudo ss -tulnp '( sport = :443 or dport = :443 )'

If you only have lsof handy:

sudo lsof -i :443 -sTCP:LISTEN

A quick packet capture to a file

Grab everything on the wire for a host and a port, save to pcap, and open it later in Wireshark:

sudo tcpdump -i any -nn -s0 -w /tmp/cap.pcap 'host 10.0.0.5 and port 443'

Human-readable one-liner, no save:

sudo tcpdump -i any -nn -vv -A 'port 53'

Which process owns this socket, this file, this mount?

sudo fuser -v /var/lib/mysql        # who has files open under this path
sudo lsof /var/log/messages         # who has this file open
sudo lsof -p 1234                   # everything this PID has open

A live top-like view of network sockets

watch -n 1 'ss -s; echo; ss -tn state established | head -20'

SSH superpowers

One hop to anywhere via a bastion

Put this in ~/.ssh/config:

Host bastion
  HostName jump.example.com
  User jbrown

Host internal-*
  User jbrown
  ProxyJump bastion

Now ssh internal-db01 tunnels through the bastion automatically. No more ssh -J on the command line every time.

Session multiplexing — make second connections instant

Also in ~/.ssh/config:

Host *
  ControlMaster auto
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlPersist 10m

First connection to a host sets up a master socket. Every connection after that for the next 10 minutes reuses it — scp, rsync, a second ssh, an Ansible run — they all open in under a second.

Local and remote port forwarding, mentally sorted

# "I want to reach THEIR port 5432 at my localhost:5432"
ssh -L 5432:db.internal:5432 bastion

# "I want THEM to reach MY localhost:3000 at their localhost:3000"
ssh -R 3000:localhost:3000 bastion

# "Make my browser's SOCKS proxy tunnel through this host"
ssh -D 1080 bastion

Generate and copy an SSH key in one go

ssh-keygen -t ed25519 -C "jbrown@$(hostname)" -f ~/.ssh/id_ed25519
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host

Disk & files

What’s eating the disk?

# Top-level usage, sorted, human-readable
du -sh -- */ 2>/dev/null | sort -hr | head -20

# Interactive explorer — install this everywhere
ncdu /var

ncdu is worth installing on every server you touch.

Find files by size

# Files over 100M under the current filesystem only
find . -xdev -type f -size +100M -printf '%s\t%p\n' | sort -nr | head

A one-shot HTTP server over any directory

Share a file with someone on the same network without standing up nginx:

python3 -m http.server 8000

Needs an auth check? Use caddy file-server --listen :8000 instead.

Rsync that survives a dropped connection

Archive, preserve attrs, compress, show progress, and resume on interrupt:

rsync -aHAXz --info=progress2 --partial --append-verify \
  /src/ user@host:/dst/

Dry-run first when --delete is involved:

rsync -aHAX --delete --dry-run /src/ /dst/

systemd & logs

Logs for one service, since last boot, follow mode

journalctl -u nginx.service -b -f

Why did this service fail?

systemctl status nginx            # quick view with last 10 log lines
journalctl -xeu nginx.service     # full story, jumps to errors

Override a unit without editing the vendor file

sudo systemctl edit nginx.service

Drops you into an editor pointed at /etc/systemd/system/nginx.service.d/override.conf. Anything you put there overlays the shipped unit and survives package upgrades.

Is this boot’s clock sane? Is NTP actually working?

timedatectl

Small quality-of-life wins

Follow a log that gets rotated

tail -f loses its grip when logrotate moves the file. -F re-opens on rotation:

tail -F /var/log/messages

Run any command whenever a file changes

# Debian/Ubuntu: apt install inotify-tools
while inotifywait -e modify ./config.yml; do
  ./reload.sh
done

Extract just about anything

# One command that handles tar, tar.gz, tar.bz2, tar.xz, zip, 7z, rar
atool -x archive.whatever

Or the old-school version that lives in my memory:

tar xaf archive.tar.anything   # auto-detects compression

Decode a JSON blob without installing anything

If jq isn’t available:

curl -s https://example.com/api | python3 -m json.tool

With jq (do install it):

curl -s https://api.example.com/things | jq '.items[] | {id, name}'

Keep a command running when you disconnect

When tmux or screen isn’t installed:

nohup ./long-job.sh > job.log 2>&1 &
disown

But really — install tmux. Ctrl-b d to detach, tmux attach to come back. Sessions survive reboots if you use tmux-resurrect.