Linux
Intermediate 15 min read Linux

Processes & Job Control

Every program running on Linux is a process with a PID, a parent, memory and a life cycle. Learn to inspect processes with ps and pgrep, terminate them with kill and pkill, manage foreground and background jobs, tune priority with nice and renice, and understand how daemons stay alive in the background.

Linux processPIDPPIDps auxpgrepkillpkillbackground jobsnicerenicedaemon
Introduction

What is this?

A process is a running instance of a program — the kernel's unit of work, with its own PID (process ID), a parent (PPID), memory space and state. When you run ls, the shell forks a child and execs it into ls; the kernel then schedules it onto a CPU. Understanding processes is how you answer 'what is eating my CPU?' and 'why won't this service die?' in production — and how every container, which is really just a group of processes in namespaces, behaves.

Motivation

Why do you need it?

  • Find the culprit: ps and top show exactly which process is burning CPU, memory or disk.
  • Kill stuck or runaway jobs cleanly instead of rebooting the whole server.
  • Run long tasks in the background with jobs, fg and bg while keeping your terminal usable.
  • Control priority with nice and renice so a critical database outcompetes a noisy log parser.
  • Understand daemons and systemd: a service is just a supervised process with a defined life cycle.
Think about it

Mental model

Imagine

A busy restaurant kitchen

Think of

Linux process management

The head chef (systemd, PID 1) assigns each cook (process) a ticket number (PID) and a station. The chef who hands out the ticket is the parent process. kill is a polite 'please stop' (SIGTERM) — the cook finishes the plate. kill -9 is security yanking the cook out mid-move with no time to wash up.

Mechanics

How it works

  • The shell calls fork(), which clones the current process into a near-identical child with a fresh PID whose PPID points back to the parent.
  • The child then calls exec() to replace its code and data with the program you actually asked for — same process, new program.
  • The kernel scheduler divides CPU time between all runnable processes, preempting them so one runaway cannot starve the machine.
  • When a process exits it leaves an exit status; the parent must wait() to reap it, otherwise the process becomes a zombie. If the parent dies first, PID 1 reparents and reaps the orphan.
  • Signals are how the kernel asks a process to act: SIGTERM (15) requests a graceful shutdown, SIGKILL (9) is delivered by the kernel and cannot be caught or ignored.

The life cycle of a Linux process from shell command to exit.

Shell
fork()
exec()
Scheduled by the kernel
exit()
Reference

Key commands

ps aux

Show every process with user, CPU, memory and the full command line.

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0 169292 14256 ?        Ss   08:10   0:02 /sbin/init
root        42  0.0  0.0  15576  4120 ?        S    08:10   0:00 /usr/sbin/sshd
appuser   1101  0.3  1.2 892332 102456 ?       Ssl  08:12   0:45 node /app/server.js
ps -p 1101 -o pid,ppid,%cpu,%mem,cmd

Inspect one PID and its parent, CPU and memory in a clean table.

  PID  PPID %CPU %MEM CMD
 1101   972  0.3  1.2 node /app/server.js
pgrep -x nginx

Find the PID of a process by exact name match.

4567
pidof nginx

Print all PIDs for a program name (handy with multiple workers).

4568 4569 4567
kill 4567

Send SIGTERM (the default) — a polite request to shut down gracefully.

kill -9 4567

Send SIGKILL — the kernel terminates the process immediately; it cannot catch this.

pkill -f 'node server.js'

Kill every process whose full command line matches the pattern.

jobs -l

List the shell's background and suspended jobs with their PIDs.

[1]+  Running                 sleep 300 &
[2]-  Stopped                 vim notes.txt
fg %1

Bring job 1 back to the foreground so you can interact with it.

bg %2

Resume a suspended job as a background process.

nice -n 10 ./backup.sh

Start a process with a lower priority (higher nice value = nicer = lower priority).

renice -n 5 -p 4567

Change the nice value of an already-running process.

Hands-on

Examples

Start, background, inspect and kill a process

Start, background, inspect and kill a process
# Start a long-running process in the background
sleep 300 &
# See it listed as a job with its PID
jobs -l
# Find its PID by name
pgrep -x sleep
# See exactly what it is doing
ps aux | grep sleep
# Ask it to stop, then confirm it is gone
kill <PID>
ps aux | grep sleep

The & puts sleep in the background so your shell stays usable. jobs lists the session's background jobs, pgrep finds the PID, and kill sends SIGTERM by default. Because sleep has nothing to clean up it exits instantly; a busy web server may need SIGKILL (kill -9) instead.

Real world

In production

  • Every cloud VM, container and Kubernetes node is a tree of processes — ps/pgrep/kill work identically inside a pod as on a bare-metal host.
  • Debugging a slow deploy starts with top and ps aux --sort=-%cpu to find the process causing the latency.
  • pkill -f 'command pattern' terminates all workers of an app (e.g. stale CI agents) without hunting for PIDs.
  • nohup or setsid keeps long jobs alive across SSH disconnects — essential for overnight migrations and batch jobs.
  • Priority tuning (nice/renice) protects latency-sensitive services like databases from batch jobs hogging the CPU.
Guidelines

Best practices

  • Always try plain kill (SIGTERM) first and give the process a few seconds; use kill -9 only as a last resort.
  • Verify what you kill: pgrep -f the pattern before pkill -f to avoid nuking unrelated processes.
  • Confirm a kill worked with ps or pgrep rather than assuming — a process can respawn (e.g. systemd Restart=always).
  • Use jobs -l to get the PID, not just the job number, when a job needs to be killed from another terminal.
  • Prefer systemctl restart over kill for supervised services, and let systemd own their life cycle.
Watch out

Common mistakes

  • Reaching for kill -9 immediately — it skips cleanup, corrupting config files and databases that need to flush.
  • Assuming PID 1 of a container is a shell: in containers the entrypoint process has PID 1 and killing it stops the container.
  • Using pkill -f on a vague pattern like 'python' and killing the wrong processes.
  • Killing a process by the PID of its parent or one of its workers and expecting the whole tree to stop.
Root cause analysis

Common issues

Error
kill: (4567) - No such process
Root cause

The PID is stale — the process already exited or you grabbed a worker PID that has since respawned.

Fix

Re-check with pgrep -x <name> or ps -p <PID> and kill the current PID.

Error
bash: bg: %1: no such job
Root cause

The job number is wrong or that job already finished.

Fix

Run jobs to list the real job specifiers, then use the correct one (e.g. fg %2).

Error
Background job dies when I close my SSH session
Root cause

The shell sends SIGHUP to its jobs on logout, and the job did not ignore it.

Fix

Launch with nohup sleep 300 & or setsid sleep 300, or run disown %1 after backgrounding it.

Error
Process will not die even after kill -9
Root cause

A process in uninterruptible kernel sleep (state D, blocked on disk/NFS I/O) cannot be killed until the I/O resolves.

Fix

Identify the I/O target with iostat and ps, fix the underlying disk or NFS issue; only then will the process die or complete.

When things break

Debugging tips

  • ps aux --sort=-%cpu ranks processes by CPU use — the top row is usually the culprit.
  • kill -l lists every signal name and number so you never guess a signal.
  • A process stuck in the D (uninterruptible sleep) state is usually blocked on I/O — check iostat, not kill.
  • Zombies are already dead: they show as Z and only disappear when their parent reaps them or systemd reparents them.
Interviews

Interview checkpoint

Practice

Hands-on lab

Manage a background job and kill it cleanly
15 min · intermediate
In progress
Objectives
  • Launch a process in the background and track it as a shell job
  • Suspend and resume jobs with Ctrl+Z, bg and fg
  • Locate a process by name and PID with pgrep and ps
  • Terminate a process gracefully with kill and forcefully with kill -9
  • Verify the process is gone and the shell stays responsive

Manage a background job and kill it cleanly

15 min · intermediate

0/6 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/6
1

What is a PID?

2

Which signal terminates a process gracefully and can be caught or ignored by the process?

3

The kill command without a signal number sends SIGKILL (kill -9).

4

What does pressing Ctrl+Z in a terminal do?

5

Which command shows every process with CPU and memory usage?

6

A stuck server process ignores kill <PID> for over ten seconds. What is your next step?

Quick reference

Cheat sheet

Inspect processes
ps auxAll processes with CPU/memory
ps -efAll processes (POSIX style)
ps -p <PID> -o pid,ppid,%cpu,%mem,cmdOne PID, chosen columns
ps aux --sort=-%cpuSorted by CPU usage
pgrep -x nginxPID by exact name
pidof nginxAll PIDs for a program
Send signals
kill <PID>SIGTERM (15), graceful
kill -9 <PID>SIGKILL, cannot be ignored
kill -STOP <PID>Suspend a running process
kill -CONT <PID>Resume a suspended process
pkill -f 'pattern'Kill by full command line
kill -lList all signal names
Job control
command &Run in the background
Ctrl+ZSuspend the foreground job
jobs -lList jobs with PIDs
fg %1Bring job 1 to the foreground
bg %1Resume job 1 in the background
nohup command &Survive logout (ignore SIGHUP)
Priority
nice -n 10 ./backup.shStart with lower priority
nice -n -5 ./urgent.shStart with higher priority (root only)
renice -n 5 -p <PID>Re-prioritise a running process
Go deeper

Official documentation