Skip to main content

    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)

    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.

    Worked example: list processes with ps and ps aux
    # 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
    Output
    # --- 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 node
    Run these in your own terminal. Your PIDs and the exact list will differ — the shape of the output is what matters.

    2️⃣ 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.

    Worked example: watch processes live with top / htop
    # 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 htop
    Output
    top - 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 bash
    Run top 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: find the sleep timer's PID
    # 🎯 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
    Output
    [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 sleep
    Run this in your own terminal. Your PID will differ from the example — that's expected.

    3️⃣ 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.

    Worked example: kill, kill -9, killall, pkill
    # 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
    Output
    $ 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 kill
    Run these against a process you started yourself (like the sleep timer above). Never guess a PID — confirm it with ps first.

    SIGTERM 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.

    Worked example: &, jobs, fg, bg, and nohup
    # 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
    Output
    [1] 4821
    [1]+  Running                 node server.js &
    [1]+  Stopped                 node server.js
    nohup: appending output to 'nohup.out'
    [2] 4855
    Job control (&, 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: background then foreground a job
    # 🎯 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)
    Output
    [1] 5102
    [1]+  Running                 sleep 60 &
    sleep 60
    Run this in your own terminal, then press Ctrl+C to stop the timer once it's back in the foreground.

    Common Errors (and the fix)

    • Reaching for kill -9 first: SIGKILL gives the process no chance to save data or release ports, which can corrupt files. Always try kill PID (SIGTERM) first; use -9 only 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 PID or ps aux | grep name before 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 with nohup command & so it keeps running.
    • bash: kill: (1842) - No such process: that PID has already exited (or you mistyped it). Re-run ps aux | grep name to get the current PID.
    • Operation not permitted: you're trying to kill a process owned by another user (often root). Re-run with sudo kill PID — but be doubly sure of the PID first.

    📋 Quick Reference

    CommandWhat it does
    ps auxList every running process with details
    ps aux | grep nameFind a process by name (read its PID)
    top / htopLive, updating process monitor
    kill PIDGraceful stop (SIGTERM) — try this first
    kill -9 PIDForce kill (SIGKILL) — last resort
    killall name / pkill -f patKill by name / by command-line pattern
    command &Run in the background
    jobs / fg %1 / bg %1List jobs / foreground / background a job
    nohup command &Keep a job running after logout

    Signals you'll actually use

    SignalNumberMeaning
    SIGTERM15Polite "shut down" — the default for kill; allows cleanup
    SIGKILL9Forced kill — cannot be caught or ignored; no cleanup
    SIGHUP1"Hang up" — sent on terminal close; also "reload config"
    SIGINT2Interrupt from the keyboard (Ctrl+C)
    SIGSTOP19Pause a process (Ctrl+Z sends the related SIGTSTP)
    SIGCONT18Resume 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: manage a background server end to end
    # 🎯 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 here
    Write and run each step in your own terminal. Use a harmless long-running command (like sleep 300) to stand in for the server.

    🎉 Lesson Complete!

    • ✅ Every running program is a process with a unique PID
    • ps aux lists processes; top/htop watch them live
    • kill PID (SIGTERM) is graceful; kill -9 (SIGKILL) is a forced last resort
    • killall and pkill -f stop processes by name or pattern
    • &, jobs, fg, and bg move 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.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service