Processes and Signals
7 pages · ~5 min✓ Reviewed
Builds on Shell Scripting. Next up: Networking Commands.
Process Mental Model
1. Process and STAT
- Process = running program with a PID and PPID (parent)
- Every process has a parent; PID 1 (init/systemd) is the ancestor
| STAT | Meaning |
|---|---|
| R | running |
| S | sleeping |
| D | I/O wait, cannot be killed |
| T | stopped |
| Z | zombie: exited, parent has not called wait |
2. Control layers
- Signalkernel's message
- Jobshell handle
- Servicesystemd: logs, restart
- Foreground jobs own the terminal
- Background jobs die on hangup unless
nohupordisown
3. Interview Point
- Zombie vs orphan? Zombie: exited, parent never called wait. Orphan: parent died, child still runs
- Why can't
kill -9remove a zombie? Already dead; only the parent's wait reaps it - PID 1 and orphans? It adopts them and reaps them on exit
Inspecting Processes with ps and top
1. ps vs top
ps= one-time snapshot, use it in scriptstop= live refresh, use it to watch loadps aux(BSD): USER PID %CPU %MEM VSZ RSS STAT COMMANDps -ef(POSIX): adds PPID and the full command line
2. Filtering
ps -p PIDshows one processpgrep -a nginxlists PID and command by nameps aux | grep [n]ginx: the [n] trick stops grep matching itself
3. top keys and load
| Key | Action |
|---|---|
P | sort by CPU |
M | sort by memory |
1 | per-core CPU |
k | kill a PID |
q | quit |
- Load average = 1, 5, 15 min values
- Load above the core count = saturated
4. Interview Point
- VSZ vs RSS? VSZ is virtual size; RSS is real RAM in use
- Top memory user?
ps aux --sort=-%mem | head, orMin top - Load average? Runnable and waiting tasks, averaged over 1/5/15 min
Jobs: Foreground and Background
1. Controlling Jobs
| Action | Keys / command | Signal |
|---|---|---|
| Start in background | cmd & | none |
| Suspend foreground | Ctrl+Z | SIGTSTP |
| Interrupt foreground | Ctrl+C | SIGINT |
jobslists this shell's jobs as [1]+fg %1brings job 1 to the foregroundbg %1resumes a stopped job in the background
- Run long cmd
- Ctrl+Zstopped
- bgkeeps running
- fgback on terminal
2. Surviving Hangup
- Closing the terminal sends SIGHUP, which kills background jobs
nohup cmd &ignores HUP; output goes to nohup.outdisown -h %nprotects a job that is already running
bash
nohup ./backup.sh & # job %1 sleep 600 & # job %2 disown -h %2 # already running
disown -h takes the job number
Only nohup writes nohup.out
disown -h just stops SIGHUP. Output still goes to the closed terminal.
3. Interview Point
- Foreground to background? Ctrl+Z, then
bg - Why do jobs die on SSH close? SIGHUP. Use
nohupordisown -h - jobs vs ps?
jobsshows this shell's jobs;psshows system processes
Signals, kill and Exit Codes
1. Signals and kill
kill PIDsends SIGTERM (15): catchable, so the process cleans up and exitskill -9 PIDsends SIGKILL: cannot be caught or ignored, no cleanup
| Num | Signal | Meaning |
|---|---|---|
| 1 | HUP | reload config / hangup |
| 2 | INT | Ctrl+C |
| 9 | KILL | uncatchable |
| 15 | TERM | default, catchable |
| 18 | CONT | resume |
| 19 | STOP | pause, uncatchable |
| 20 | TSTP | Ctrl+Z |
2. Kill by name
killall name: by process namepkill -f pattern: by full command line- Preview first with
pgrep -a pattern: matches can hit unrelated processes
3. Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| nonzero | failure |
| 126 | not executable |
| 127 | command not found |
| 128+N | killed by signal N |
| 137 / 143 | SIGKILL / SIGTERM |
echo $? | last command's code |
4. Interview Point
- Why TERM before KILL? TERM lets the process clean up; KILL skips cleanup
- What does 137 mean? 128+9: killed by SIGKILL, often OOM or a stop timeout
- Did the last command succeed?
echo $?, and 0 means yes
systemd Services and journalctl
1. Unit Files
- PID 1 starts and supervises every service
- Unit file:
/etc/systemd/system/app.service [Unit]ordering,[Service]how to run,[Install]boot target
ini
[Unit] After=network.target [Service] ExecStart=/usr/bin/app User=app Restart=on-failure [Install] WantedBy=multi-user.target
2. Lifecycle
| Command | Effect |
|---|---|
start / stop | now only, gone after reboot |
enable / disable | boot only, not started now |
enable --now | enable + start |
restart | stop, then start a new process |
reload | re-read config, same process |
- Edited a unit? Run systemctl daemon-reload
systemctl status appshows state;systemctl --failedlists failures
3. Logs with journalctl
| Flag | Shows |
|---|---|
-u app | one service's logs |
-f | follow live |
-n 100 | last 100 lines |
--since '1 hour ago' | recent window |
-p err | errors and worse |
-b | current boot only |
- Crash loop:
systemctl status app, thenjournalctl -u app -b -p err
start is not enable
start does not survive a reboot, and enable does not start now. Use enable --now for both.
Process Control Cheat Sheet
1. Inspect
ps aux/ps -ef: snapshot;pgrep -a name: find PIDstopkeys: P CPU, M mem, 1 cores, k kill, q quit- STAT: R run, S sleep, D I/O wait, T stopped, Z zombie
2. Jobs and signals
bash
nohup ./backup.sh & # job %1, survives hangup sleep 600 & # job %2 disown -h %2 # already running job jobs # Ctrl+Z, bg %n, fg %n
| Command | Effect |
|---|---|
kill PID | SIGTERM (15) |
kill -9 PID | last resort |
kill -HUP PID | reload |
pkill -f pattern | match full command line |
killall name | kill by name |
3. Exit codes and systemd
| Code | Meaning |
|---|---|
| 0 | ok |
| 1 | general error |
| 126 | not executable |
| 127 | not found |
| 130 | Ctrl+C |
| 137 | SIGKILL |
| 143 | SIGTERM |
- Read the last code with
echo $? systemctl start|stop|restart|status app- enable --now = boot + start; daemon-reload after unit edits
bash
journalctl -u app -f -n 100 --since '1 hour ago' -p err
Check yourself
What does this print?
137- 128 + 9, because SIGKILL is signal 9
sleep 60 & kill -9 $! wait $! echo $?
You edited app.service and ran systemctl restart app, but the old behaviour remains. What did you miss?
systemctl daemon-reload- Without it, systemd keeps the old unit definition
ps aux | grep nginx shows a line, yet nginx is not running. Why?
- grep matches its own command line
- Use
grep [n]ginxorpgrep -a nginx