Processes & Signals

Linux · Lesson 18 of 32 7 min read Updated

Every running program on Linux is a process. Your shell is a process, every command you type starts one, and a server runs dozens of them all the time: the web server, the database, SSH, the logging service. When something is slow or stuck, the first job is to find the right process and decide what to do with it.

In this lesson you will list processes, read their details, watch them live, stop them with signals, and juggle several jobs in one terminal.

What a process is

When you run a program, the kernel creates a process for it and gives it a PID (process ID), a unique number. Each process also records its PPID (parent process ID), the process that started it, and the user it runs as, which decides what it is allowed to do. The very first process, PID 1, is systemd on Ubuntu; every other process descends from it.

Terminal
echo $$
ps
Output
2481
    PID TTY          TIME CMD
   2481 pts/0    00:00:00 bash
   2617 pts/0    00:00:00 ps

$$ is the PID of the current shell. Plain ps shows only processes in this terminal: your shell and ps itself, which ends as soon as it has printed.

ps: a snapshot of all processes

ps aux lists every process on the system. (The options come from old BSD style, so there is no dash.) Pipe it into grep or head:

Terminal
ps aux | head -n 4
ps aux | grep [n]ginx
Output
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.3  22588 13312 ?        Ss   08:01   0:02 /sbin/init
root           2  0.0  0.0      0     0 ?        S    08:01   0:00 [kthreadd]
root         845  0.0  0.1  11280  2016 ?        Ss   08:01   0:00 nginx: master process /usr/sbin/nginx
www-data     846  0.0  0.1  12960  5124 ?        S    08:01   0:00 nginx: worker process
ColumnMeaning
USER, PIDOwner and process ID
%CPU, %MEMShare of processor and memory
RSSReal memory in use, in KB
TTYTerminal; ? means none (a background service)
STATState: R running, S sleeping, D waiting for disk, T stopped, Z zombie
COMMANDThe command line

Names in square brackets such as [kthreadd] are kernel threads. The [n]ginx trick stops grep from matching its own command line. Even simpler is pgrep, which prints matching PIDs: pgrep -a nginx shows PIDs with their command lines. ps -ef is the other common style, and ps -eo pid,user,%mem,cmd --sort=-%mem | head shows the biggest memory users first.

top and htop: watch live

top refreshes the list every few seconds, with the busiest processes at the top:

Terminal
top
Output
top - 10:42:13 up  2:41,  1 user,  load average: 0.08, 0.12, 0.10
Tasks: 118 total,   1 running, 117 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.3 us,  0.7 sy,  0.0 ni, 97.8 id,  0.2 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3911.2 total,   2180.4 free,    702.6 used,   1259.8 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   3208.6 avail Mem

The load average shows how many processes were running or waiting to run, averaged over 1, 5 and 15 minutes. As a rough guide, a load that stays above the number of CPU cores means the machine is overloaded. id is idle CPU, and wa is time spent waiting for the disk. Inside top, press M to sort by memory, P by CPU, k to kill a process and q to quit.

htop (sudo apt install htop) is a friendlier version with colours, bars for each CPU core, mouse support and a tree view (F5). Many people install it on every server.

Signals and kill

You control a process by sending it a signal, a small numbered message. Despite its name, kill simply sends signals:

SignalNumberMeaning
SIGTERM15Please stop: the default. The program can clean up first
SIGINT2Interrupt; what Ctrl+C sends
SIGHUP1"Hang up"; many services reload their config on it
SIGKILL9Stop immediately. Cannot be caught or ignored
SIGSTOP / SIGCONT19 / 18Pause / resume
Terminal
kill 3120
kill -HUP 845
pkill -u kabir python3
kill -9 3120

The first line asks process 3120 to finish politely. The second tells nginx's master process to reload its configuration. pkill sends a signal by name instead of PID (here only to Kabir's python3 processes), and killall does the same by exact program name. You can only signal your own processes unless you use sudo.

Jobs: foreground and background

A command normally runs in the foreground: the shell waits for it to finish. Put & at the end to run it in the background and get your prompt back at once. Bash calls these jobs and numbers them per terminal.

Terminal
sleep 100 &
sleep 200 &
jobs
kill %1
jobs
Output
[1] 4012
[2] 4013
[1]-  Running                    sleep 100 &
[2]+  Running                    sleep 200 &
[1]-  Terminated                 sleep 100
[2]+  Running                    sleep 200 &

[1] 4012 means job 1 with PID 4012. %1 refers to job 1. Other job controls:

  • Ctrl+Z pauses the foreground job and returns the prompt.
  • bg resumes a paused job in the background; fg brings a job back to the foreground (fg %2).
  • Background jobs still die when you close the terminal or your SSH session drops. nohup command & keeps one running after you log out, writing its output to nohup.out. For anything long-lived, a systemd service (see Services with systemd & systemctl) or a terminal multiplexer such as tmux is the better tool.

Advanced: priority with nice

Every process has a niceness from -20 (highest priority) to 19 (lowest). A "nice" process lets others go first. Start heavy jobs, such as large backups, with low priority so the website stays fast:

Terminal
nice -n 15 tar -czf /backup/site.tar.gz /var/www/shop
sudo renice -n 5 -p 3120

Normal users can only make their processes nicer (higher numbers); lowering the number needs sudo. The NI column in top shows the value.

Common mistakes

  • Reaching for kill -9 first. Try plain kill and give the program time to clean up.
  • Killing the wrong PID. PIDs are reused. Check with ps -p PID -o pid,user,cmd right before you kill.
  • Expecting & jobs to survive logout. Use nohup, tmux or a systemd service.
  • Confusing Ctrl+Z with Ctrl+C. Ctrl+Z only pauses; the process still holds memory and files until you fg or kill it.

Key points

  • Every process has a PID, a parent (PPID) and an owner; PID 1 is systemd.
  • ps aux lists all processes; pgrep -a name finds them; top and htop show them live.
  • kill PID sends SIGTERM (polite); kill -9 sends SIGKILL (forced); kill -HUP often reloads config.
  • & starts a background job; jobs, fg, bg and Ctrl+Z manage jobs in the current terminal.
  • nice and renice lower or raise a process's priority.

Exercise

Start sleep 500 in the background and sleep 600 in the foreground. Pause the foreground one with Ctrl+Z and resume it in the background. List your jobs, then find the PID of the sleep 500 process with pgrep, stop it politely with kill, and bring the other job to the foreground and stop it with Ctrl+C.

Show solution
Terminal
sleep 500 &
sleep 600
bg
jobs
pgrep -a sleep
kill 5120
fg
Output
[1] 5120
^Z
[2]+  Stopped                    sleep 600
[2]+ sleep 600 &
[1]-  Running                    sleep 500 &
[2]+  Running                    sleep 600 &
5120 sleep 500
5121 sleep 600
[1]-  Terminated                 sleep 500
sleep 600
^C

Ctrl+Z shows ^Z and marks the job Stopped; bg restarts it in the background. pgrep -a gives the PIDs, and plain kill sends SIGTERM. fg brings job 2 back, and Ctrl+C sends SIGINT to end it.

Quick Quiz

1. What is PID 1 on Ubuntu?

2. Which signal does kill 1234 send by default?

3. What does Ctrl+Z do to a running foreground command?

4. In top, a 2-core server shows load average: 6.10, 5.80, 5.95. What does that suggest?

Learn Linux with a mentor

Free lessons get you started. Our Ethical Hacking & Cyber Security training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call