Reference · Daily SDE

Cheatsheets — Linux, Docker, Kubernetes & the Daily Toolbelt

Field guide for what an SDE types every day. Each section is a quick-scan table plus the gotchas that bite in production. Code blocks copy on click.

1 · Linux — Files & Permissions

Filesystem moves, listing, and the chmod bits that confuse everyone.

Navigation & listing

CommandPurpose
ls -lahLong, human-sized, all (incl. dotfiles).
ls -lt | headNewest files first.
tree -L 2 -aTwo levels deep, all files.
cd -Jump back to previous dir.
pushd /x / popdDir stack — explore then return.
readlink -f fileResolve symlink to absolute path.

File ops

CommandPurpose
cp -a src dstArchive: preserve perms, links, timestamps.
rsync -avhP src/ dst/Resumable, progress, trailing slash matters.
mv -i a bInteractive — prompt before overwrite.
ln -s target linkSymbolic link.
stat fileInode, perms, atime/mtime/ctime.
du -sh * / du -hd1Per-entry size of cwd.
df -hDisk free per mount.
ncdu /Interactive disk usage explorer.

Permissions & ownership

# numeric: r=4 w=2 x=1   user|group|other
chmod 755 script.sh        # rwxr-xr-x
chmod 600 ~/.ssh/id_rsa    # rw------- (private keys MUST be 600)
chmod -R u+rwX,go-w dir    # capital X = exec only on dirs / already-exec files
chown -R user:group dir
umask 022                  # default mask: new files = 644, dirs = 755
sudo chmod g+s shareddir   # setgid on dir = new files inherit group

Find & locate

find . -type f -name "*.log" -mtime -1            # modified in last 24h
find . -type f -size +100M                         # bigger than 100MB
find . -name node_modules -type d -prune -exec rm -rf {} +
find . -name "*.tmp" -delete
fd 'pattern'                                       # rust find, faster
locate filename                                    # uses prebuilt db (mlocate)

2 · Text Processing — grep · sed · awk

Filter, transform, count. Pipe everything.

grep / ripgrep

grep -rni 'TODO' src/                 # recursive, line nums, ignore-case
grep -E '(error|fatal)' app.log       # extended regex
grep -v '^#' conf                     # invert: skip comments
grep -A3 -B1 'panic' log              # 3 after, 1 before
grep -c 'Exception' app.log           # count matches
rg -t py 'def main' .                 # ripgrep, only .py files
rg -l 'pattern'                       # files with matches only

sed — stream edit

sed -n '5,10p' file               # print lines 5-10
sed -i 's/foo/bar/g' file         # in-place replace (BSD/macOS: sed -i '' ...)
sed -i.bak 's/old/new/g' file     # safer: keep .bak
sed '/^$/d' file                  # delete blank lines
sed 's/[[:space:]]*$//' file      # trim trailing whitespace

awk — column tool

awk '{print $1, $NF}' file              # first + last field
awk -F: '$3 >= 1000 {print $1}' /etc/passwd   # custom delim
awk '{sum+=$1} END {print sum}' nums    # sum column
ps aux | awk '$3 > 50.0'                # rows where CPU > 50%
awk 'NR==1 || /ERROR/' log              # header + matches

cut · sort · uniq · tr · wc

cut -d, -f1,3 file.csv            # CSV columns 1 & 3
sort -k2 -n file                  # numeric sort by col 2
sort | uniq -c | sort -rn         # frequency table (top hitters)
tr 'A-Z' 'a-z' < file             # lowercase
wc -l file                        # line count
paste a b                         # side-by-side merge
xargs -n1 -P4 -I{} curl {}        # parallel: 4 jobs

3 · Processes & System

Who's running what, and who's eating the box.

List & signal

CommandPurpose
ps auxEvery process, BSD format (CPU, MEM, START).
ps -ef --forestTree view — see parent/child.
pgrep -af nodePIDs whose cmdline matches.
pkill -9 -f myappKill by full cmdline pattern.
kill -TERM <pid>15 = polite shutdown. Default.
kill -KILL <pid>9 = uncatchable. Last resort.
kill -HUP <pid>1 = reload config (nginx, sshd).
nohup cmd &Detach from terminal; survives logout.
disown -h %1Detach existing job from shell.

Live monitors

top                  # classic
htop                 # color, scroll, tree (F5)
btop                 # modern eye-candy
iotop                # disk IO per process
iftop                # network bandwidth per host
glances              # aggregate dashboard
free -h              # RAM/swap snapshot
uptime               # load avg over 1/5/15 min
vmstat 1             # one sample/sec: cpu, io, swap
iostat -xz 1         # per-device IO stats

What's open / what's listening

ss -tulnp                       # TCP/UDP, listening, with PID (modern)
netstat -tulnp                  # legacy alias
lsof -i :8080                   # who has port 8080
lsof -p <pid>                   # files+sockets opened by pid
lsof +D /var/log                # who has files under /var/log open
fuser -v /mnt/data              # processes using a path

systemd

systemctl status nginx
systemctl start|stop|restart|reload nginx
systemctl enable --now nginx           # start now + on boot
systemctl list-units --failed
journalctl -u nginx -f                  # follow service logs
journalctl --since "10 min ago"
journalctl -p err -b                    # errors since last boot

4 · Networking — diagnose in 30s

Layer probes

CommandLayer / Purpose
ip a / ip rL3: addrs and routing table.
ping -c 4 hostL3: reachable? RTT?
traceroute host / mtr hostL3: path. mtr = continuous.
dig +short example.comDNS: A record only.
dig @8.8.8.8 MX example.comDNS: query specific server.
host -a example.comDNS: every record type.
nslookup example.comDNS: legacy but on every box.
nc -zv host 443L4: port reachable from here?
curl -I https://x.comL7: headers only.
tcpdump -i any -n port 443Packet capture on the wire.

Common debug flow

# 1. DNS resolves?
dig +short api.svc.local
# 2. Route exists?
ip route get 10.0.0.5
# 3. TCP port open from here?
nc -zv api.svc.local 443
# 4. TLS handshake works?
openssl s_client -connect api.svc.local:443 -servername api.svc.local
# 5. App layer responds?
curl -v https://api.svc.local/health

5 · Bash Scripting Essentials

The strict-mode preamble, parameter expansion, and the loops you actually use.

Strict-mode preamble

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

# -e  exit on error
# -u  fail on unset variables
# -o pipefail  fail if any pipe stage fails
# IFS  safer word-splitting (no spaces)

Variables & parameter expansion

name="alice"
echo "${name^^}"           # ALICE  (uppercase)
echo "${name,,}"           # alice  (lowercase)
echo "${name:-anon}"       # default if unset/empty
echo "${name:+set}"        # 'set' only if name has value
file="/var/log/app.log"
echo "${file##*/}"         # app.log    (basename)
echo "${file%/*}"          # /var/log   (dirname)
echo "${file%.log}.bak"    # swap extension
arr=(a b c); echo "${#arr[@]}"   # 3

Conditionals & loops

if [[ -f "$f" ]]; then echo "exists"; fi
[[ -d "$d" ]] && echo "dir"
[[ "$x" =~ ^[0-9]+$ ]] && echo "numeric"
[[ -z "$s" ]]   # empty
[[ -n "$s" ]]   # non-empty

for f in *.log; do gzip "$f"; done
for i in {1..5}; do echo $i; done
while read -r line; do echo "$line"; done < file
case "$1" in start) ... ;; stop) ... ;; *) ... ;; esac

Functions, traps, args

cleanup() { rm -f /tmp/lock; }
trap cleanup EXIT INT TERM

main() {
  local input="${1:?usage: main <input>}"
  echo "processing $input"
}
main "$@"

6 · SSH, scp, rsync

Keys & config

ssh-keygen -t ed25519 -C "you@host"           # modern, fast, small
ssh-copy-id user@host                          # push pubkey
ssh-add ~/.ssh/id_ed25519                      # load into agent

# ~/.ssh/config
Host bastion
  HostName 1.2.3.4
  User ubuntu
  IdentityFile ~/.ssh/prod_ed25519
Host prod-*
  ProxyJump bastion
  User ubuntu

Common usage

ssh -A user@host                  # forward agent (carefully)
ssh -L 8080:localhost:80 host     # local fwd: localhost:8080 → host:80
ssh -R 9000:localhost:9000 host   # reverse fwd: expose your service to host
ssh -D 1080 host                  # SOCKS proxy on :1080
ssh host 'tail -f /var/log/syslog'

scp file user@host:/path/
rsync -avhP --delete src/ user@host:/dst/    # mirror, with progress

7 · Docker — Containers & Images

90% of your daily commands. Memorize these.

Containers

CommandPurpose
docker psRunning. Add -a for stopped.
docker run --rm -it img bashInteractive, auto-cleanup on exit.
docker run -d --name api -p 8080:80 imgDetached, named, port mapped.
docker exec -it api bashShell into running container.
docker logs -f --tail 100 apiFollow last 100 lines.
docker stop api && docker rm apiStop & remove.
docker inspect apiFull JSON: env, mounts, IP, state.
docker statsLive CPU/mem per container.
docker cp api:/etc/app.conf .Copy out (or in).
docker top apiProcesses inside container.

Images

docker images
docker pull alpine:3.20
docker build -t myapp:1.0 .
docker build --target builder -t myapp:dev .   # multi-stage target
docker tag myapp:1.0 registry/me/myapp:1.0
docker push registry/me/myapp:1.0
docker rmi myapp:old
docker image prune -a                          # remove unused images
docker history myapp:1.0                       # layer breakdown
docker save myapp:1.0 | gzip > myapp.tgz       # offline transfer
gunzip -c myapp.tgz | docker load

Volumes & networks

docker volume create pgdata
docker run -v pgdata:/var/lib/postgresql/data postgres
docker run -v "$PWD":/app -w /app node:20 npm test    # bind mount
docker volume ls
docker volume prune

docker network create app-net
docker run --network app-net --name db postgres
docker run --network app-net --name api myapp     # api can resolve "db"
docker network inspect app-net

Cleanup — reclaim disk

docker system df                  # what's using space
docker system prune -a --volumes  # nuke unused images, networks, volumes
docker container prune
docker builder prune              # build cache

8 · Dockerfile Patterns

Multi-stage Node example

# syntax=docker/dockerfile:1.7

# ---- build stage ----
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
RUN npm run build

# ---- runtime stage ----
FROM node:20-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
USER node
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://127.0.0.1:3000/health || exit 1
CMD ["node", "dist/server.js"]

Layer-cache rules

.dockerignore

.git
node_modules
**/*.log
.env*
dist
coverage
.DS_Store

9 · docker compose

Minimal stack

# compose.yaml
services:
  api:
    build: .
    ports: ["8080:8080"]
    environment:
      DATABASE_URL: postgres://app:app@db:5432/app
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: app
      POSTGRES_DB: app
    volumes: [pgdata:/var/lib/postgresql/data]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  pgdata:

Daily commands

docker compose up -d                 # start in background
docker compose up --build api        # rebuild then up
docker compose logs -f api db
docker compose ps
docker compose exec api sh
docker compose run --rm api npm test # one-off, then remove
docker compose stop                  # stop, keep state
docker compose down                  # stop + remove containers/networks
docker compose down -v               # ALSO remove named volumes (data loss!)
docker compose config                # render effective merged config

10 · Kubernetes — kubectl

Context & namespaces

kubectl config get-contexts
kubectl config use-context prod
kubectl config set-context --current --namespace=app-prod
kubens app-prod                        # if you have kubectx/kubens
kubectl cluster-info

Inspect

CommandPurpose
kubectl get pods -A -o wideAll ns, with node + IP.
kubectl get pods -l app=apiLabel selector.
kubectl describe pod <p>Events, status, mounts.
kubectl logs -f <p> -c sidecarStream container logs.
kubectl logs <p> --previousLogs from prior crash.
kubectl exec -it <p> -- shShell in pod.
kubectl top podCPU/mem (needs metrics-server).
kubectl get events --sort-by=.lastTimestampLatest cluster events.

Apply / rollout / debug

kubectl apply -f k8s/                # apply directory
kubectl diff -f deploy.yaml          # what would change
kubectl rollout status deploy/api
kubectl rollout history deploy/api
kubectl rollout undo deploy/api      # back one revision
kubectl scale deploy/api --replicas=5
kubectl set image deploy/api api=myapp:1.4

kubectl port-forward svc/api 8080:80
kubectl cp pod:/var/log/app.log .
kubectl debug -it pod/api --image=busybox --target=api  # ephemeral container

Pod manifest skeleton

apiVersion: apps/v1
kind: Deployment
metadata: { name: api, labels: { app: api } }
spec:
  replicas: 3
  selector: { matchLabels: { app: api } }
  template:
    metadata: { labels: { app: api } }
    spec:
      containers:
      - name: api
        image: myapp:1.0
        ports: [{ containerPort: 8080 }]
        resources:
          requests: { cpu: 100m, memory: 128Mi }
          limits:   { cpu: 500m, memory: 512Mi }
        readinessProbe:
          httpGet: { path: /ready, port: 8080 }
          periodSeconds: 5
        livenessProbe:
          httpGet: { path: /health, port: 8080 }
          initialDelaySeconds: 30

11 · Git — Daily & Rescue

Daily flow

git status -sb                       # short + branch info
git switch -c feat/x                 # create+switch (modern)
git add -p                           # stage hunks interactively
git commit -m "feat: x"
git commit --amend --no-edit         # tweak last commit
git push -u origin feat/x

git pull --rebase                    # avoid merge bubbles
git fetch --all --prune              # clean tracking branches
git log --oneline --graph --decorate --all
git diff main...feat/x               # changes on feature since branch point

Stash / restore / clean

git stash push -m "wip" -u           # include untracked
git stash list
git stash pop                        # apply + drop
git restore file                     # discard worktree changes
git restore --staged file            # unstage
git clean -fd                        # remove untracked (DESTRUCTIVE)

Rewrite history (local only!)

git rebase -i HEAD~5                 # squash/reorder/edit
git rebase --onto main old-base feat # transplant range
git cherry-pick <sha>
git revert <sha>                     # safe: new commit that undoes

Recovery

git reflog                           # every HEAD movement (90 days)
git reset --hard HEAD@{2}            # jump back to a reflog entry
git fsck --lost-found                # dangling commits
git bisect start && git bisect bad && git bisect good v1.0
# git auto-checks out midpoints; mark good/bad until culprit found

12 · curl · jq · HTTPie

curl

curl -fsSL https://x.com/install.sh | bash
#  -f fail-on-error  -s silent  -S show-err  -L follow-redirects

curl -i https://api.x.com/v1/me                              # show headers + body
curl -H 'Authorization: Bearer $T' https://api.x.com/me
curl -X POST -H 'Content-Type: application/json' \
     -d '{"name":"alice"}' https://api.x.com/users
curl -F 'file=@./image.png' https://api.x.com/upload         # multipart
curl -o out.bin -C - https://x.com/big.bin                   # resume download
curl -w '%{http_code} %{time_total}\n' -o /dev/null -s URL   # timing only

jq — JSON surgery

curl -s api.x/users | jq '.'                       # pretty
jq '.users[] | .name'                              # extract
jq '.users[] | select(.active) | .id'              # filter
jq -r '.users[].email'                             # raw (no quotes)
jq '{name, email}'                                 # pick fields
jq '.users | length'
jq 'group_by(.role) | map({role: .[0].role, n: length})'
jq -s 'add' a.json b.json                          # slurp + merge arrays

HTTPie (friendlier)

http GET api.x.com/me Authorization:"Bearer $T"
http POST api.x.com/users name=alice age:=30      # := for non-string
http --download big.bin URL

13 · Vim & tmux — Survive Remote Boxes

Vim — bare minimum

KeysAction
i / a / oInsert before / after / new line below.
Esc or Ctrl-[Back to normal mode.
:w / :q / :wq / :q!Write / quit / write+quit / discard.
dd / yy / pDelete line / yank line / paste.
u / Ctrl-rUndo / redo.
/foo · n · NSearch forward · next · prev.
:%s/foo/bar/gcReplace all, confirm each.
gg / G / :42Top / bottom / line 42.
v · V · Ctrl-vVisual char · line · block.
ciw / ci" / ci(Change inside word / quotes / paren.

tmux — sessions that survive disconnect

tmux new -s work          # start named session
tmux ls
tmux attach -t work
# inside: prefix is Ctrl-b
#   c    new window      n / p  next / prev window
#   "    split horiz     %      split vert
#   o    next pane       arrows move between panes
#   d    detach          x      kill pane
#   [    scroll mode (q to exit)

14 · Performance & Debug

The USE checklist

Trace what a process is doing

strace -p <pid> -f -e trace=network,read,write   # syscalls
strace -c -p <pid>                                # summary table on Ctrl-C
ltrace -p <pid>                                   # library calls
perf top -p <pid>                                 # live hot functions
perf record -g -p <pid> -- sleep 30 && perf report
sudo cat /proc/<pid>/status                       # state, threads, RSS
sudo ls -l /proc/<pid>/fd                         # open file descriptors

Memory & OOM

free -h
cat /proc/meminfo | head
dmesg -T | grep -i 'killed process'      # OOM kill events
smem -k -p                                # PSS-aware per-process memory

Quick "what's slow?" recipe

uptime              # load trend
vmstat 1 5          # cpu / io / swap
iostat -xz 1 5      # disk pressure
ss -s               # socket totals
dmesg -T | tail     # kernel complaints
journalctl -p err -b | tail

15 · Package Managers — Cross-Distro

Actionapt (Debian/Ubuntu)dnf (RHEL/Fedora)pacman (Arch)brew (macOS)
refresh indexapt updatednf check-updatepacman -Sybrew update
installapt install pkgdnf install pkgpacman -S pkgbrew install pkg
removeapt remove pkgdnf remove pkgpacman -R pkgbrew uninstall pkg
upgrade allapt full-upgradednf upgradepacman -Syubrew upgrade
searchapt search foodnf search foopacman -Ss foobrew search foo
infoapt show pkgdnf info pkgpacman -Si pkgbrew info pkg
which file ownsdpkg -S /pathrpm -qf /pathpacman -Qo /pathbrew list pkg
list installedapt list --installeddnf list --installedpacman -Qbrew list

Language-level

# Python
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
pipx install black                     # global CLI tools, isolated
uv pip install -r requirements.txt     # fast modern alt

# Node
npm ci                                 # reproducible from lockfile
npm run dev
pnpm install                           # fast, content-addressed
nvm use 20                             # version switch

# Go / Rust
go install github.com/x/y@latest
cargo install ripgrep