Linux Gotchas
Permission Traps
chmod 777fixes nothing, breaks everything — find the actual owner/group issue- Setuid on scripts is ignored for security — only works on binaries
chown -Rfollows symlinks outside target directory — use--no-dereference- Default umask 022 makes files world-readable — set 077 for sensitive systems
- ACLs override traditional permissions silently — check with
getfacl
Process Gotchas
killsends SIGTERM by default, not SIGKILL — process can ignore itnohupdoesn't work if process already running — usedisowninstead- Background job with
&still dies on terminal close withoutdisownornohup - Zombie processes can't be killed — parent must call wait() or be killed
kill -9skips cleanup handlers — data loss possible, use SIGTERM first
Filesystem Traps
- Deleting open file doesn't free space until process closes it — check
lsof +L1 rm -rf /path /with accidental space = disaster — userm -rf /path/trailing slash- Inodes exhausted while disk shows space free — many small files problem
- Symlink loops cause infinite recursion —
find -Lfollows them /tmpcleared on reboot — don't store persistent data there
Disk Space Mysteries
- Deleted files held open by processes —
lsof +L1shows them, restart process to free - Reserved blocks (5% default) only for root —
tune2fs -m 1to reduce - Journal eating space —
journalctl --vacuum-size=500M - Docker overlay eating space —
docker system prune -a - Snapshots consuming space — check LVM, ZFS, or cloud provider snapshots
Networking
localhostand127.0.0.1may resolve differently — check/etc/hosts- Firewall rules flushed on reboot unless saved —
iptables-saveor use firewalld/ufw persistence netstatdeprecated — usessinstead- Port below 1024 requires root — use
setcapfor capability instead - TCP TIME_WAIT exhaustion under load — tune
net.ipv4.tcp_tw_reuse
SSH Traps
- Wrong permissions on ~/.ssh = silent auth failure — 700 for dir, 600 for keys
- Agent forwarding exposes your keys to remote admins — avoid on untrusted servers
- Known hosts hash doesn't match after server rebuild — remove old entry with
ssh-keygen -R - SSH config Host blocks: first match wins — put specific hosts before wildcards
- Connection timeout on idle — add
ServerAliveInterval 60to config
Systemd
systemctl enabledoesn't start service — also needstartrestartvsreload: restart drops connections, reload doesn't (if supported)- Journal logs lost on reboot by default — set
Storage=persistentin journald.conf - Failed service doesn't retry by default — add
Restart=on-failureto unit - Dependency on network:
After=network.targetisn't enough — usenetwork-online.target
Cron Pitfalls
- Cron has minimal PATH — use absolute paths or set PATH in crontab
- Output goes to mail by default — redirect to file or
/dev/null - Cron uses system timezone, not user's — set TZ in crontab if needed
- Crontab lost if edited incorrectly —
crontab -l > backupbefore editing - @reboot runs on daemon restart too, not just system reboot
Memory and OOM
- OOM killer picks "best" victim, often not the offender — check dmesg for kills
- Swap thrashing worse than OOM — monitor with
vmstat - Memory usage in
freeincludes cache — "available" is what matters - Process memory in
/proc/[pid]/status— VmRSS is actual usage - cgroups limit respected before system OOM — containers die first
Commands That Lie
dfshows filesystem capacity, not physical disk — check underlying devicedudoesn't count sparse files correctly — file appears smaller than disk usageps auxmemory percentage can exceed 100% (shared memory counted multiple times)uptimeload average includes uninterruptible I/O wait — not just CPUtopCPU percentage is per-core — 400% means 4 cores maxed