Questions I explored while building these scripts, and what I took away from each.
ps stands for "process status." The flags break down as:
a— show processes from all usersu— user-oriented format (shows %CPU, %MEM, username, etc.)x— include background processes not attached to a terminal
Together, ps aux means "show me everything running on this machine, for everyone, with full detail."
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1 2 3 4 5 6 7 8 9 10 11
- USER — who owns the process
- PID — unique process ID (used to kill or inspect it)
- %CPU / %MEM — current CPU and RAM consumption
- VSZ — virtual memory (total the process could use)
- RSS — resident set size (actual physical RAM in use)
- TTY — terminal it's attached to (
?= background daemon) - STAT — state: S = sleeping, R = running, Z = zombie
- START — when the process launched
- TIME — total CPU time consumed
- COMMAND — the actual program running
grep searches text line by line and prints every line that contains the search term. It returns whole lines, not individual words.
# grep "apple" in a file containing "apple", "pineapple", "banana"
# → returns "apple" AND "pineapple" (both contain "apple")
# grep "^apple" — the ^ means "starts with"
# → returns only "apple" (pineapple starts with "pine")^ is a regex anchor meaning "start of line."
grep "User"matches "User" anywhere in the line — including inside file paths like/home/User2/backup.shgrep "^User"matches "User" only at the very beginning of the line
Without ^, you can accidentally pick up other users' processes if your username appears in their command paths.
When you pipe into grep, the header row gets filtered out. Fix:
ps aux | head -n 1 && ps aux | grep "^$USER"Or use grep's "extended" OR pattern:
ps aux | grep -E "^USER|^$USER"A zombie is a process that has finished executing but whose parent never acknowledged its completion ("reaped" it). It's dead but still occupies a slot in the process table. One or two are harmless; hundreds can prevent new processes from starting.
Spot them with: ps aux | grep Z
A process stuck in an unintended loop, consuming CPU/memory/disk without doing useful work. A common symptom is runaway log writing — a process retries a failed operation in a tight loop and logs the error thousands of times per second, filling up the disk.
Prevention: exponential backoff on retries, log rotation, and resource monitoring.
A memory leak happens when code creates objects or connections but never releases them. Common causes:
- Collections that grow without bounds (lists that store every request forever)
- Unclosed database or network connections
- Caches with no max size or expiration policy
Prevention: close resources explicitly, cap collection sizes, set cache eviction rules, load-test to watch for steady memory climbs.
| Syntax | When to use |
|---|---|
$var |
Works most of the time |
"$var" |
Safest default — protects against empty values and spaces |
${var} |
When the name is ambiguous, e.g. ${var}items |
Rule of thumb: always use "$var" and you'll almost never have a bug.
read -p "Enter a number: " num
echo "You entered $num"Writing just num on its own tries to run a command called num. The read command is what actually pauses and captures input.
When setting a variable: no $ → num=5, read num
When using a variable: add $ → echo $num
-k3— sort by column 3-r— reverse order (highest first)-n— numeric sort (so 10 doesn't come before 2)
head -n 5 prints only the first 5 lines. Useful after sorting to get a "top N" view.
[ ] is the older test syntax — if a variable is empty and unquoted, it causes a syntax error. [[ ]] is newer and handles empty variables gracefully even without quotes. Both work fine if you always quote your variables.