Learn Linux - Process Management & Resource Monitoring
Series/Learn Linux/Episode 13
Episode 13 of 31

Learn Linux - Process Management & Resource Monitoring

Every running program is a process living in its own ecosystem. This episode dissects PID/PPID and process states, practices monitoring with ps, top, and htop, controls processes through signals, and runs background tasks with nohup, screen, and tmux.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Introduction

After episode 12 where we covered the shell, environment variables, and .bashrc customization — from VAR=x vs export VAR, startup files, to your first bash script — you can now give complex instructions to the system. But there's something running behind the scenes every time you type a command: processes. Every program, from the simplest ls to an Nginx serving thousands of requests, is a process living in the kernel, consuming CPU and RAM, and can be seen, monitored, and controlled.

In this episode, we'll open up Linux's "engine room": what PID and PPID are, what process states like R, S, and Z (zombie) mean, how to read a snapshot with ps, monitor real-time with top/htop, and how to stop processes with the right signals. By the end of the episode, you'll know exactly what happens when a server "hangs" and how to handle it without panicking. Let's begin.

Main Discussion

Processes: The Work Units Inside Linux

When the kernel runs a program, it creates a process — an entity with its own program code, data, and execution context. Every process is given a PID (Process ID), a unique number within the system. The process that created it is called the parent, with a PPID (Parent Process ID). This is why all processes in Linux form a tree: there's one root at number 1, and every process is a branch of another process.

Imagine a highly organized restaurant. The head chef (PID 1, systemd or init) hires kitchen staff. Any staff member who recruits another is recorded as the parent of their recruit. If a staff member suddenly quits, their recruits become "orphaned" and are adopted by the head chef. This analogy explains why every orphaned process is eventually reparented to PID 1.

Every process also has a state reflecting what it's currently doing. The four states you'll see most often:

StateMeaningWhen it happens
R (Running)The process is actively executing codeCurrently using CPU
S (Sleeping)The process is waiting for something (I/O, timer)Waiting on disk, network, or events
D (Uninterruptible sleep)Waiting for I/O that can't be interruptedWaiting on a problematic disk (hard to kill)
Z (Zombie)The process is dead but not yet "buried" by its parentThe parent hasn't called wait() yet

State Z is one of the phenomena that most often panics beginner admins. A zombie is a process that has finished its job but whose entry hasn't been cleaned from the process table, because its parent hasn't called wait(). Zombies don't consume CPU or RAM — they're just a leftover identity. They pile up only if the parent is buggy (never calls wait) or the parent itself is stuck.

Viewing Processes: ps, pstree

The main command for taking a process snapshot is ps. The two most used syntaxes: ps aux (BSD format) and ps -ef (POSIX format). Both display a full process list; the difference is just output style and column names.

Snapshot of all processes with ps aux
ps aux
ps aux shows every process along with CPU/RAM usage

The ps aux output you'd typically see (truncated here):

Example ps aux output (truncated)
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 167520 11544 ?        Ss   Aug01   0:15 /sbin/init
arman    12345  2.5  3.1 620000 128000 ?       Ssl  Aug01  12:04 node server.js
nginx    23456  0.1  0.2 210000 20000 ?        S    Aug01   0:30 nginx: worker process
arman    34567  0.0  0.0      0     0 ?        Z    Aug01   0:00 [defunct]
Columns USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

Some columns you must recognize:

  • PID — the process identity; this is what kill uses.
  • STAT — the process state (S sleeping, R running, Z zombie).
  • %CPU / %MEM — the percentage of usage relative to the total.
  • COMMAND — the actual command that was run (including arguments).

Notice the fourth row: STAT Z and the command name [defunct] are the classic signs of a zombie process. If you see it, no need to panic — it's just waiting for its parent to call wait(). If they pile up, check the parent, not the zombie itself.

Meanwhile, pstree presents processes as a family tree, exactly like the restaurant genealogy earlier:

Viewing the process hierarchy with pstree
pstree
pstree shows parent-child relationships visually
plaintext
systemd─┬─nginx───2*[nginx]
        ├─sshd───sshd───bash───node───4*[node]
        └─systemd-journal

Real-Time Monitoring: top and htop

ps is a photo; top is a video camera. top refreshes its display every few seconds, sorts processes by CPU usage, and shows a system summary at the top — load average, process count, CPU usage per component, and memory usage. Run it with top then press q to quit.

Monitoring the system in real time
top
 
# Install htop — an interactive display with mouse & colors
sudo apt install htop
htop
top for built-in monitoring, htop for interactive & convenient

htop is a friendlier replacement for top: colorful, scrollable, mouse support, and a process killer command (F9) without needing to remember PIDs. For production servers, top remains the standard because it's always available; htop is an added convenience. Both monitor the same thing: who's consuming the most resources right now.

Tip

In top, press M to sort by memory usage and P to return to CPU ordering — a quick way to find "naughty" processes. To see processes of a specific user, run top -u arman. The habit of reading top output whenever a server starts slowing down is a skill that will pay off hugely in episode 24 (performance tuning).

Controlling Processes with Signals

This is the most important part. Linux doesn't "kill" processes haphazardly — it sends signals, and the process decides how to respond. Signals are the standard inter-process communication method; you send them via kill <PID>, killall, or pkill. Some signals you must memorize:

SignalNumberDefault behaviorUsage
SIGTERM15The process is politely asked to stopStopping a process normally
SIGKILL9Forced to stop, cannot be refusedA completely stuck process that won't die
SIGHUP1Hang up — often used to reload confignginx reload without restart
SIGINT2Interrupt — same as Ctrl+CCanceling a foreground process
SIGSTOP19Process is paused (can be resumed)Like Ctrl+Z
Sending signals to processes
# Send SIGTERM (15) — a polite stop request
kill 12345
 
# Send a specific signal
kill -15 12345      # same as kill 12345
kill -9 12345       # SIGKILL — force stop
kill -1 12345       # SIGHUP — request a config reload
 
# Kill by name (not PID)
killall node
pkill -f "node server.js"
The correct order: try TERM first, then KILL

Important

Never go straight to kill -9. That signal cuts a process off roughly without giving it a chance to clean up — files being written can get corrupted, databases can lose data, and in-memory state is lost. The correct order: send SIGTERM (15), wait a few seconds, only then consider SIGKILL (9) if the process is truly stubborn. The analogy: SIGTERM is saying "please stop now", SIGKILL is cutting power straight from the main switch.

pkill -f "pattern" has both power and danger: it kills all processes whose command line matches the pattern. A wrong pattern and you can kill processes you never intended. Use pgrep -f first to see what will match before pkill.

Foreground & Background: Managing Many Tasks

So far all our commands run in the foreground — the terminal is locked until the command finishes. For long-running processes (like a dev server), there's a background mechanism:

Running processes in the background
# Run directly in the background with the & sign
sleep 300 &
 
# List the jobs in this shell session
jobs -l
 
# Move a job to the foreground
fg %1
 
# Pause a foreground process with Ctrl+Z, then resume it in the background
# (after pressing Ctrl+Z)
bg %1
& to background, Ctrl+Z to pause, jobs to monitor, fg/bg to move

The full map: command & starts a job in the background; Ctrl+Z temporarily stops a foreground job; jobs lists jobs with %n numbers; fg %n returns one to the foreground; bg %n resumes a paused job in the background. Note the important difference: a background job isn't a "detached" process — it's still tied to the session terminal. Close that terminal, and the job dies with it.

Note

Why does a background job die when the terminal closes? Because the kernel sends SIGHUP (hang up) to all processes tied to the terminal when it closes. To detach a process from the terminal, we need a tool that "adopts" the process — that's what nohup, screen, and tmux are for.

Persistent Processes: nohup, screen, and tmux

For jobs that must survive an SSH disconnect — database migrations, big builds, or servers that must run 24/7 — there are three levels of solution:

nohup (no hang up) is the simplest: it ignores the SIGHUP signal, so the process survives after the terminal closes. Its output is redirected to nohup.out.

Running a SIGHUP-immune process
nohup ./migrate-data.sh > migrasi.log 2>&1 &
 
# The process keeps running; check the results later
tail -f migrasi.log
nohup + & = a process that survives a closed terminal

screen and tmux are terminal multiplexers — they create terminal sessions living separately from the physical terminal. You can detach a session, close SSH, and come back later; the process keeps running and the output is still there. tmux is the modern, most popular standard:

tmux basics: sessions that survive
# Create a new session named "deploy"
tmux new -s deploy
 
# Inside the session: Ctrl+B then D to detach
# (processes inside keep running)
 
# List all active sessions
tmux ls
 
# Return to the session
tmux attach -t deploy
Detach with Ctrl+B then D, return with tmux attach

Tip

Which one to use when? nohup for a single command that needs to survive. tmux when you need an interactive workspace — running several panes, scrolling output, and returning to the same session after a disconnect. For production servers that must auto-restart on crash, don't use any of the three — that's systemd's job, which will be the topic of episode 14.

Common Mistakes in Process Management

MistakeSymptomSolution
kill -9 directly without SIGTERMCorrupted data, process has no time to clean upSend SIGTERM first, wait, then SIGKILL
Panicking at the sight of zombie processesWant to kill a zombie (it won't work)Check the parent; zombies are cleaned up by their parent
pkill -f with too broad a patternUnexpected processes get killed toopgrep -f first to see the matches
Killing a PID from ps without verificationWrong process killed (PID reused)Verify the name & start time, or use pgrep
Closing the terminal with a background jobThe job dies (SIGHUP)Use nohup, screen, or tmux
kill on a D-state processWon't die even with -9Wait for the I/O to finish; -9 doesn't affect D

One thing worth remembering: PIDs can be reused by the system. The process you see in ps now could already be dead and its PID taken by another process. That's why pkill/killall (name-based) are safer for "kill them all" and pgrep is useful for verifying before per-PID kill.

Conclusion

In this episode 13 we've opened up Linux's engine room: understanding PID/PPID and process states including zombies, reading snapshots with ps aux and hierarchies with pstree, monitoring real-time with top/htop, controlling processes via the signals SIGTERM/SIGKILL/SIGHUP, and moving work to the background with &, jobs, fg, bg, plus making it persistent with nohup, screen, and tmux. The most important lesson: processes are citizens of the system with rights and protocols — treat them with respect via the right signals, and the system will cooperate with you.

But there's one question hanging since earlier: who keeps important processes always running — even after a crash or reboot? The answer is systemd, the modern init system that's process number 1 on almost every distro. In the next episode 14 we'll discuss systemd and service management: systemctl, journalctl, through to writing your own service unit files. See you there!

Learn Linux - Process Management & Resource Monitoring | Learn Linux