Cheat sheet · Linux and the Command Line for Developers
Linux & Shell cheat sheet
The Linux command line for developers and admins: files, permissions, processes, pipes, scripts, SSH, services and the first two minutes on a slow server. The shell expands things before the command runs.
blogs · jp-blogs.vercel.app/cheatsheets/series/linux-shell
Files and pathsLesson 0 →
- One tree from
/./etcconfig,/varrun-time data,/homeusers,/tmpscratch,/procand/syslive kernel views. - Absolute paths start with
/..is here,..is up,~is home,cd -goes back. - The shell finds commands by searching
PATHin order.type NAMEsays builtin or program. - A hard link is a second name for one inode. A symlink holds a path and can dangle.
- ls -lah
- Long list, hidden files, readable sizes
- find . -name '*.log'
- Search a whole tree
- head -n 5 / tail -n 5 / wc -l
- Start, end, line count
- mkdir -p a/b/c
- Make nested folders
- ln -s TARGET LINK
- Symbolic link
- du -sh * / df -h
- Size of names / free space per file system
- stat FILE / file FILE
- Inode details / detected type
Quotes, variables, exit statusLesson 0 →
| Syntax | Meaning |
|---|---|
'text' | Literal, nothing expands |
"$var" | Variables expand, spaces stay together |
$(cmd) | Command substitution |
*.txt | Glob; no match stays as plain text |
$? / $$ / $! | Last status / shell PID / last background PID |
A && B, A || B | Run B if A succeeds / fails |
Tip: Exit status 0 is success. command -v NAME shows where a command comes from. Look (ls) before you rm.
Reading permissionsLesson 1 →
-rwxr-x---is type, owner, group, others. The kernel uses the first matching class only.- Octal: r=4, w=2, x=1.
750isrwxr-x---. Use644files,755programs and folders,600/700private. Avoid777. - On a directory:
rlists,wcreates and deletes,xlets you pass through. Deleting depends on the directory. - Users and groups are numbers (UID, GID). Names live in
/etc/passwd; hashes in/etc/shadow.
- chmod 640 FILE / chmod u+x FILE
- Set the mode / add execute for owner
- chown user:group FILE
- Change owner (needs root)
- umask 022
- New files 644, folders 755
- id / groups
- Who am I, which groups
Special bits, sudo, trapsLesson 1 →
| Bit | Effect | Example |
|---|---|---|
| setuid | Runs as the file owner (ignored on scripts) | passwd |
| setgid (dir) | New files inherit the group | Team folder |
| sticky | Delete only your own files | /tmp |
Watch out: sudo cmd > file fails: your shell does the redirect. Use cmd | sudo tee file. Root ignores mode bits, so test as the service user (sudo -u).
Permission deniedis the mode bits.Operation not permittedis ownership or capability.umaskremoves bits from new files. New files never start withx.
Processes and signalsLesson 2 →
| STAT | Meaning |
|---|---|
R / S | Running / sleeping (normal) |
D | Uninterruptible wait (disk, network mount); cannot be killed |
T | Stopped (Ctrl-Z or SIGSTOP) |
Z | Zombie: dead, parent has not collected it |
- ps -eo pid,ppid,stat,cmd
- Choose your columns
- pstree -p / pgrep -af NAME
- Tree / find by name, show command
- kill PID
- SIGTERM (15), the polite default
- kill -9 PID
- SIGKILL, cannot be caught. Last resort.
- kill -STOP PID / -CONT PID
- Pause / resume
- kill -0 PID
- Does it exist? Sends nothing
Jobs, exit codes, limitsLesson 2 →
| Exit code | Meaning |
|---|---|
0 | Success |
126 / 127 | Not executable / command not found |
128+N | Killed by signal N |
137 / 143 | SIGKILL (9) / SIGTERM (15) |
cmd &backgrounds a job. Closing the terminal sends SIGHUP: usenohup,disown,tmuxor systemd.- Ctrl-C is SIGINT, Ctrl-Z suspends, Ctrl-D ends input. Fix a zombie by fixing its parent.
- PID 1 ignores signals without a handler: handle
SIGTERMor use an init in containers. nice/reniceset CPU priority.timeout 5 cmdandulimitset limits.
Watch out: pkill -f matches full command lines, even your own. Check with pgrep -af first.
Redirection and pipesLesson 3 →
| Syntax | Effect |
|---|---|
> f / >> f | Overwrite / append stdout |
2> f | stderr to a file |
> f 2>&1 | Both to f (order matters) |
< f | Read stdin from f |
> /dev/null | Throw output away |
a \| b | stdout of a into b; last status wins |
a \| tee f \| b | Save the middle of a pipeline |
cmd > fileempties the file first. Never read and write the same file.set -o pipefailmakes a pipeline fail if any stage fails. A pipe carries only stdout.
grep, sort, sed, awkLesson 3 →
- grep -inrlcvwoq -E -F
- Ignore case, number, recurse, list, count, invert, word, only, quiet, regex, literal
- sort | uniq -c | sort -rn | head
- The top-N idiom
- sort -n
- Numeric (text order puts 100 before 9)
- cut -d, -f2 / tr a-z A-Z
- Pick a field / translate characters
- sed 's/old/new/g'
- Replace;
-iedits in place - awk '{s+=$3} END{print s}'
- Sum column 3
- awk -F: '$3>=1000{print $1}'
- Filter by field
Watch out: grep exits 0 match, 1 none, 2 error. Under set -e, no match kills the script: use || true or if. uniq needs sorted input.
find and xargsLesson 3 →
find . -name '*.log' -mtime +7 \
-size +1M
find . -type f -print0 \
| xargs -0 -r wc -l
find . -name '*.tmp' -exec rm {} +
find . -name '*.tmp' \
| xargs echo rm # dry run-exec {} + batches and is faster than \;.
-print0withxargs -0is safe for names with spaces.xargs -rskips an empty run.- Build pipelines one stage at a time, and filter early.
Scripting basicsLesson 4 →
#!/usr/bin/env bash
set -euo pipefail
tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT
for f in ./*.log; do
[[ -e $f ]] || continue
echo "$f" >> "$tmp"
done
while IFS= read -r line; do echo "$line"; done < "$tmp"Quote every expansion. Glob in loops, never loop over ls.
[[ ]]beats[ ]. Use-gt/-ltfor numbers;>and<compare text.- Functions:
localvariables,returna status, print data, errors to>&2. A && B || Cis not if/else. Options:getopts. Debug withbash -x, lint with ShellCheck.
set -e and other script trapsLesson 4 →
| Flag | Effect |
|---|---|
-e | Stop when a command fails |
-u | Unset variable is an error |
-o pipefail | Pipeline fails if any part fails |
set -ehas holes: functions used inif,local x=$(...),(( )),let.- A
while readat the end of a pipe runs in a subshell; its variables vanish. /bin/shis dash on Debian and Ubuntu.trap cleanup EXITruns on every exit except SIGKILL.- macOS ships bash 3.2 with no associative arrays.
SSH, rsync, tunnelsLesson 5 →
- ssh-keygen -t ed25519
- Make a key pair (set a passphrase)
- ssh -G HOST / ssh -v HOST
- Show settings / show login steps
- rsync -avn SRC/ DEST/
- Dry run;
-nfirst, always - rsync -av --delete SRC/ DEST/
- Mirror, removing extras
- ssh -L 8080:db:5432 HOST
- Local forward;
dbresolved on HOST - ssh -J BASTION HOST
- Jump host (
ProxyJump)
- SSH checks the server (
known_hosts) first, then you (authorized_keys). Private key mode600. - Vague "Permission denied"? Read the server log:
bad ownership or modes,account is locked. SRC/copies the contents,SRCcopies the folder. Put names in~/.ssh/configwithIdentitiesOnly yes.
Network toolsLesson 5 →
- ss -ltnp
- Listening TCP ports and their process
- nc -zv HOST PORT
- Is this port open?
- dig NAME
- Ask DNS
- curl -sS -m 5 -f URL
- Time limit, fail on HTTP errors
- curl -w '%{time_total}' URL
- Time breakdown of a request
| curl exit | Meaning |
|---|---|
7 | Refused: host up, nothing listening |
28 | Timed out: firewall, unreachable, or silent server |
Tip: A 404 still exits 0 without -f. A service bound to loopback only is a common cause of "running but unreachable". Do not trust ping alone.
Packages, services, cronLesson 6 →
- apt update
- Refresh lists only
- apt upgrade -s
- Simulate first, then drop
-s - apt remove / apt purge
- Keep config / delete config too
- systemctl enable --now NAME
- Start now and at boot
- systemctl daemon-reload
- After editing a unit
- systemd-analyze verify NAME
- Check a unit file
- A unit has
[Unit],[Service],[Install]. systemd ignores bad lines silently. Care withRestart=. - Cron fields: minute hour day-of-month month day-of-week (0-7). If both day fields are set, either matches.
- Cron has a tiny environment (
PATH=/usr/bin:/bin,sh): use full paths, redirect output, escape%. - Timers add journal logs, catch-up after downtime and load spreading.
Slow server: first two minutesLesson 7 →
uptime: compare load average withnproc. Linux load counts tasks waiting on disk.top/vmstat 1:rrun queue,bblocked,si/soswap,waI/O wait. Ignore line one.free -h: read available, not free. Cache is not a problem.df -h,df -i,iostat: space, inodes, disk speed.ss -ltnpandcurl -w: network. Then logs:journalctlortail -F.
| Disk "full" kind | Check | Fix |
|---|---|---|
| No space | df -h, du | Delete or rotate |
| No inodes | df -i | Remove many small files |
| Deleted, still open | df > du; lsof +L1 | Restart process; truncate with : > f |
Interview one-linersLesson 8 →
| Question | Short answer |
|---|---|
cmd > f 2>&1 vs 2>&1 > f? | First sends both to f. Second sends stderr to the old stdout. |
| umask 027? | Files 640, folders 750. |
| Zombie? | Finished child nobody collected. Fix the parent. |
| 137 vs 143? | SIGKILL vs SIGTERM. TERM first, always. |
[ ] vs [[ ]]? | [[ ]] does not word-split. Safer in bash. |
Why tee with sudo? | The shell does the redirect, not sudo. |
| Hard vs symlink? | Same inode vs a file holding a path. |
| Server is slow? | Clarify, CPU, memory, disk, network, logs, fix, verify. |
| Cron job fails but works by hand? | Small environment: use full paths. |
A cheat sheet is a reminder, not a teacher. Each card links to the lesson that explains it step by step.