Lesson 6 • Intermediate
Process Management ⚙️
By the end of this lesson you'll be able to see every program running on your machine, find a stuck app by its PID, stop it cleanly (or force it as a last resort), and run long jobs in the background that survive after you log out.
What You'll Learn
- What a process and a PID are, and why every program has one
- List processes with ps aux and monitor them live with top / htop
- Stop processes with kill, kill -9, killall, and pkill
- Foreground vs background: &, jobs, fg, and bg
- Keep jobs alive after logout with nohup
- How signals work — SIGTERM (graceful) vs SIGKILL (forced)
ps is the staff directory; top is a live dashboard of who's busy. kill politely asks someone to pack up and leave (SIGTERM); kill -9 is security physically removing them mid-task (SIGKILL) — fast, but they drop whatever they were holding.1️⃣ Processes, PIDs & ps
A process is just a running program — your browser, a server, even the shell you're typing in. The operating system gives each one a unique PID (Process ID), a number you use to refer to it. The ps command lists processes. On its own it shows only yours in the current terminal; the classic ps aux shows every process with useful columns like %CPU and %MEM. Pipe it into grep to find one program by name.
# Every running program is a "process" with a unique number: its PID.
# ps shows you those processes. Two forms cover almost everything.
# 1) ps with no options: just YOUR processes in THIS terminal
ps
# 2) ps aux: EVERY process on the machine, with details
# a = all users u = user-readable columns x = include background ones
ps aux
# 3) Pipe into grep to find one program by name (here, node)
ps aux | grep node# --- ps ---
PID TTY TIME CMD
2417 pts/0 00:00:00 bash
2980 pts/0 00:00:00 ps
# --- ps aux (trimmed) ---
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 168940 11500 ? Ss 09:01 0:02 /sbin/init
sam 1842 0.4 2.1 998240 87340 ? Sl 09:14 0:09 node server.js
sam 2417 0.0 0.2 22360 5180 pts/0 Ss 09:20 0:00 bash
# --- ps aux | grep node ---
sam 1842 0.4 2.1 998240 87340 ? Sl 09:14 0:09 node server.js
sam 2990 0.0 0.0 9032 888 pts/0 S+ 09:21 0:00 grep node2️⃣ Live Monitoring with top & htop
ps gives you a single snapshot. When you want to watch what's happening — which process is eating your CPU right now — use top, a live monitor that refreshes every couple of seconds. Inside top, press P to sort by CPU, M to sort by memory, and q to quit. htop is a friendlier, colour version with scrolling and mouse support — install it once and you'll never go back.
# ps is a SNAPSHOT (one moment). top is a LIVE, updating monitor —
# like Task Manager / Activity Monitor in the terminal.
top # built-in everywhere. Press q to quit.
# Press P to sort by CPU, or M to sort by memory.
htop # friendlier, colour version (you may need to install it)
# Ubuntu/Debian: sudo apt install htop
# macOS: brew install htoptop - 09:22:41 up 2:21, 1 user, load average: 0.18, 0.21, 0.20
Tasks: 142 total, 1 running, 141 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.0 us, 1.1 sy, 0.0 ni, 95.7 id, 0.2 wa
MiB Mem : 3919.4 total, 612.0 free, 1480.8 used, 1826.6 buff/cache
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1842 sam 20 0 998240 87340 31200 S 4.0 2.1 0:09.12 node
988 sam 20 0 712400 54120 40880 S 1.3 1.3 0:31.04 gnome-shell
2417 sam 20 0 22360 5180 3360 S 0.0 0.1 0:00.07 bashtop in your own terminal and press q to exit. The numbers update continuously, so yours will look busier than this static snapshot.🎯 Your Turn: Find a Process's PID
Fill in the blanks marked ___ using the hints, then run it. You'll start a throwaway timer and track down its PID — the exact skill you need before you can stop anything.
# 🎯 YOUR TURN — replace each ___ then run it in your terminal.
# Goal: find the PID of a running program so you can manage it.
# 1) Start something to look for (a tiny background sleep timer)
sleep 300 & # the & runs it in the background; prints "[1] <PID>"
# 2) List ALL processes (a, user columns, include background)
ps ___ # 👉 the three letters that mean "all + user + background"
# 3) Narrow the list to just your sleep timer
ps aux | ___ sleep # 👉 the command that filters lines containing "sleep"
# ✅ Expected output (your PID will differ):
# [1] 3456
# sam 3456 0.0 0.0 8200 760 pts/0 S 09:25 0:00 sleep 300[1] 3456
sam 3456 0.0 0.0 8200 760 pts/0 S 09:25 0:00 sleep 300
sam 3470 0.0 0.0 9032 888 pts/0 S+ 09:25 0:00 grep sleep3️⃣ Stopping Processes: kill & Signals
To stop a process you send it a signal — a short message the kernel delivers. kill PID sends SIGTERM (signal 15): a polite "please shut down" that lets the program save its work, close files, and free up ports. Only if a process ignores that and truly hangs do you reach for kill -9 PID, which sends SIGKILL (signal 9) — the kernel destroys it instantly, with no chance to clean up. Don't know the PID? killall name targets processes by exact name, and pkill -f "pattern" matches anywhere in the command line.
# A "signal" is a message you send to a process. The two that matter most:
# SIGTERM (15) "please shut down" — polite; the program can save & clean up.
# SIGKILL (9) "stop NOW" — the kernel yanks it; no cleanup possible.
# kill sends SIGTERM by default — ALWAYS try this first.
kill 1842 # ask process 1842 to shut down gracefully
# If (and only if) it ignores SIGTERM and hangs, force it with -9 (SIGKILL):
kill -9 1842 # last resort — cannot be caught, blocked, or cleaned up
# Don't know the PID? Target the program by name instead:
killall node # send SIGTERM to EVERY process named exactly "node"
pkill -f "server.js" # match anywhere in the full command line, not just the name
# Pause and resume without killing:
kill -STOP 1842 # freeze the process (it stops using CPU)
kill -CONT 1842 # let it carry on$ kill 1842
$ ps -p 1842
PID TTY TIME CMD # (no row) -> the process has exited cleanly
$ killall node
$ pkill -f "server.js"
node: no process found # nothing matched -> nothing to killSIGTERM vs SIGKILL — get the order right
Always try kill PID (SIGTERM) first and give it a second or two. Reaching straight for kill -9 can corrupt files, leave locks behind, or strand a database mid-write, because the program never gets to finish what it was doing. kill -9 is the emergency brake, not the parking brake.
4️⃣ Foreground, Background & nohup
When you run a command normally it runs in the foreground and holds your terminal hostage until it finishes. Add a trailing & to run it in the background so you keep working. jobs lists this shell's background and paused jobs; fg pulls one to the foreground and bg resumes a paused one in the background. Press Ctrl+Z to pause whatever's in the foreground. One catch: a plain background job dies when you close the terminal (it receives SIGHUP). Start it with nohup — "no hangup" — and it survives logout.
# A FOREGROUND process owns your terminal until it finishes.
# A BACKGROUND process runs while you keep using the same terminal.
# 1) Start in the background with a trailing & -> prints [job] PID
node server.js & # e.g. "[1] 4821" — job number 1, PID 4821
# 2) See this shell's jobs (+ marks the most recent)
jobs # "[1]+ Running node server.js &"
# 3) Already started something in the FOREGROUND? Pause it with Ctrl+Z,
# then push it to the background, or pull it back:
bg # resume the paused job IN the background
fg %1 # bring job number 1 back to the FOREGROUND
kill %1 # kill a job by its %job-number (not its PID)
# 4) nohup = "no hangup": keep running after you close the terminal / log out.
# Without it, closing the terminal sends SIGHUP and the job dies.
nohup node server.js & # output goes to ./nohup.out
nohup ./backup.sh > backup.log 2>&1 & # send output to your own log file[1] 4821
[1]+ Running node server.js &
[1]+ Stopped node server.js
nohup: appending output to 'nohup.out'
[2] 4855&, bg, fg, jobs) only works in a real interactive shell, so run these in your own terminal.Pro Tip
nohup ... & is fine for a quick task, but for a real server you want it to restart on crash and start on boot. Reach for a process manager: pm2 for Node apps, or systemd services on Linux. tmux and screen are also great for keeping interactive sessions alive over SSH.
🎯 Your Turn: Background a Job, Then Reclaim It
Fill in the blanks, then run it. You'll send a timer to the background, confirm it's there with jobs, and pull it back to the foreground.
# 🎯 YOUR TURN — replace each ___ then run it in your terminal.
# Goal: start a job in the background, list it, then pull it to the front.
# 1) Run a 60-second timer in the background
sleep 60 ___ # 👉 the single character that means "run in background"
# 2) List the background/stopped jobs in this shell
___ # 👉 the command that lists this shell's jobs
# 3) Bring job number 1 back to the foreground
fg ___ # 👉 how you refer to "job number 1" (hint: starts with %)
# ✅ Expected output (PID will differ):
# [1] 5102
# [1]+ Running sleep 60 &
# sleep 60 <- now in the foreground (Ctrl+C to stop it)[1] 5102
[1]+ Running sleep 60 &
sleep 60Ctrl+C to stop the timer once it's back in the foreground.Common Errors (and the fix)
- Reaching for
kill -9first: SIGKILL gives the process no chance to save data or release ports, which can corrupt files. Always trykill PID(SIGTERM) first; use-9only when it genuinely won't stop. - Killing the wrong PID: PIDs get reused, and a quick glance is easy to misread. Confirm with
ps -p PIDorps aux | grep namebefore you kill. Killing the wrong number can take down something important. - Background job vanishes after logout: a plain
command &receives SIGHUP and dies when the terminal closes. Start it withnohup command &so it keeps running. bash: kill: (1842) - No such process: that PID has already exited (or you mistyped it). Re-runps aux | grep nameto get the current PID.Operation not permitted: you're trying to kill a process owned by another user (often root). Re-run withsudo kill PID— but be doubly sure of the PID first.
📋 Quick Reference
| Command | What it does |
|---|---|
| ps aux | List every running process with details |
| ps aux | grep name | Find a process by name (read its PID) |
| top / htop | Live, updating process monitor |
| kill PID | Graceful stop (SIGTERM) — try this first |
| kill -9 PID | Force kill (SIGKILL) — last resort |
| killall name / pkill -f pat | Kill by name / by command-line pattern |
| command & | Run in the background |
| jobs / fg %1 / bg %1 | List jobs / foreground / background a job |
| nohup command & | Keep a job running after logout |
Signals you'll actually use
| Signal | Number | Meaning |
|---|---|---|
| SIGTERM | 15 | Polite "shut down" — the default for kill; allows cleanup |
| SIGKILL | 9 | Forced kill — cannot be caught or ignored; no cleanup |
| SIGHUP | 1 | "Hang up" — sent on terminal close; also "reload config" |
| SIGINT | 2 | Interrupt from the keyboard (Ctrl+C) |
| SIGSTOP | 19 | Pause a process (Ctrl+Z sends the related SIGTSTP) |
| SIGCONT | 18 | Resume a paused process |
Frequently Asked Questions
Q: What's the difference between kill and kill -9?
Plain kill sends SIGTERM (signal 15), a polite request to shut down that lets the program save files, close connections, and release ports first. kill -9 sends SIGKILL (signal 9), which the kernel enforces immediately — the program gets no chance to clean up. Always try kill first; use kill -9 only when a process is truly stuck.
Q: How do I find the PID of a process?
Use ps aux | grep <name> to list matching processes (the PID is the number in the second column), or pgrep <name> to print just the PIDs. For a process using a specific port, lsof -i :3000 shows which PID owns port 3000.
Q: Why did my background process die when I closed the terminal?
Closing a terminal sends a SIGHUP ('hang up') signal to its jobs. A plain command & job receives it and exits. Start it with nohup command & (no hangup) so it ignores SIGHUP and keeps running after you log out.
Q: What's the difference between a foreground and a background process?
A foreground process owns your terminal — you can't type another command until it finishes. A background process (started with a trailing &) runs while you keep using the same terminal. Use jobs to list them, fg to pull one to the foreground, and bg to resume a paused one in the background.
Q: What's the difference between kill, killall, and pkill?
kill targets one process by its PID (kill 1842). killall targets every process whose name matches exactly (killall node). pkill matches a pattern, and with -f it matches anywhere in the full command line (pkill -f "server.js"), which is handy when several programs share a name.
Mini-Challenge: Launch, Inspect & Stop a Server
No blanks this time — just a brief and an outline. Write the commands yourself, run them in your terminal, and check the result against the expected note. This is the exact loop you'll run whenever a server misbehaves.
# 🎯 MINI-CHALLENGE: launch, inspect, and stop a server cleanly.
# Write the commands yourself — no blanks this time. Steps:
#
# 1. Start a long-running job in the background that survives logout,
# sending its output to "app.log". (hint: nohup ... > app.log 2>&1 &)
# 2. Find its PID by filtering ps for the program name. (hint: ps aux | grep ...)
# 3. Ask it to shut down GRACEFULLY first. (hint: kill PID)
# 4. Only if it refuses to stop, force it. (hint: kill -9 PID)
#
# ✅ Expected: step 1 prints "[1] <PID>"; after step 3, "ps -p <PID>"
# shows no row — the process has exited.
# your commands heresleep 300) to stand in for the server.🎉 Lesson Complete!
- ✅ Every running program is a process with a unique PID
- ✅
ps auxlists processes;top/htopwatch them live - ✅
kill PID(SIGTERM) is graceful;kill -9(SIGKILL) is a forced last resort - ✅
killallandpkill -fstop processes by name or pattern - ✅
&,jobs,fg, andbgmove work between foreground and background - ✅
nohup command &keeps a job alive after you log out - ✅ Next lesson: Permissions and Users —
chmod,chown, and managing access
Sign up for free to track which lessons you've completed and get learning reminders.