RED HAT ENTERPRISE LINUX

Managing Processes

Investigate, Control, and Terminate Running Processes

CIS126RH | RHEL System Administration 1
Mesa Community College

Learning Objectives

1
View and monitor processes

Use ps, top, and other tools to examine running processes

2
Understand process states

Know what Running, Sleeping, Stopped, and Zombie mean

3
Send signals to processes

Use kill, killall, and pkill to control and terminate processes

4
Manage job control and priority

Work with foreground/background jobs and adjust process priority

What is a Process?

A process is a running instance of a program. Each process has a unique Process ID (PID), its own memory space, and associated resources.

PID

Unique numeric identifier assigned to each process by the kernel

PPID

Parent Process ID - the process that spawned this one

State

Current status: Running, Sleeping, Stopped, or Zombie

Priority

Nice value determining CPU scheduling preference

Process 1: The first process (PID 1) is systemd on RHEL. It's the ancestor of all other processes and the init system.

Process States

R
Running / Runnable
S
Interruptible Sleep
D
Uninterruptible Sleep
T
Stopped
Z
Zombie
I
Idle (kernel thread)

R - Running: Actively using CPU or ready to run

S - Sleeping: Waiting for an event (input, timer)

D - Disk Sleep: Waiting for I/O, cannot be interrupted

T - Stopped: Suspended by signal (Ctrl+Z) or debugger

Z - Zombie: Finished but parent hasn't read exit status

I - Idle: Kernel thread not doing work

Viewing Processes: ps

# Show processes for current user in current terminal
[student@server ~]$ ps
    PID TTY          TIME CMD
   1234 pts/0    00:00:00 bash
   5678 pts/0    00:00:00 ps

# Show all processes (BSD style - commonly used)
[student@server ~]$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY   STAT START   TIME COMMAND
root         1  0.0  0.1 171820 13256 ?     Ss   Dec07   0:03 /usr/lib/systemd/systemd
root         2  0.0  0.0      0     0 ?     S    Dec07   0:00 [kthreadd]
student   1234  0.0  0.0 226524  5432 pts/0 Ss   09:00   0:00 -bash
apache    5678  0.0  0.2 274448 20480 ?     S    09:01   0:00 /usr/sbin/httpd

# Show all processes (UNIX style)
[student@server ~]$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Dec07 ?        00:00:03 /usr/lib/systemd/systemd
root         2     0  0 Dec07 ?        00:00:00 [kthreadd]
student   1234  1200  0 09:00 pts/0    00:00:00 -bash
ps aux vs ps -ef: Both show all processes. aux is BSD style (no dash), -ef is UNIX style. Choose based on which columns you need.

Understanding ps Output

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.1 0.2 171820 13256 ? Ss Dec07 0:03 /usr/lib/systemd/systemd apache 5678 2.5 1.0 274448 81920 ? S 09:01 0:45 /usr/sbin/httpd -DFOREGROUND student 9012 0.0 0.0 226524 5432 pts/0 S+ 10:30 0:00 vim document.txt root 9999 95.0 0.1 125000 10240 ? R 10:35 5:00 /opt/app/runaway
Column Description
USERProcess owner
PIDProcess ID
%CPUCPU usage percentage
%MEMMemory usage percentage
VSZVirtual memory size (KB)
RSSResident Set Size - physical memory used (KB)
TTYControlling terminal (? = none/daemon)
STATProcess state + modifiers
STARTStart time or date
TIMECumulative CPU time
COMMANDCommand with arguments

Filtering ps Output

# Find processes by name using grep
[student@server ~]$ ps aux | grep httpd
apache    5678  0.0  0.2 274448 20480 ?     S    09:01   0:00 /usr/sbin/httpd
apache    5679  0.0  0.2 274448 20480 ?     S    09:01   0:00 /usr/sbin/httpd
student   9876  0.0  0.0  12345   980 pts/0 S+   10:40   0:00 grep --color=auto httpd

# Exclude grep itself from results
[student@server ~]$ ps aux | grep [h]ttpd
[student@server ~]$ ps aux | grep httpd | grep -v grep

# Use pgrep to find PIDs by name
[student@server ~]$ pgrep httpd
5678
5679

# pgrep with more detail
[student@server ~]$ pgrep -a httpd
5678 /usr/sbin/httpd -DFOREGROUND
5679 /usr/sbin/httpd -DFOREGROUND

# Find processes by user
[student@server ~]$ ps -u apache
[student@server ~]$ pgrep -u apache

Real-time Monitoring: top

[student@server ~]$ top
top - 10:45:32 up 1 day,  2:30,  2 users,  load average: 0.15, 0.10, 0.05
Tasks: 245 total,   1 running, 244 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.3 us,  1.0 sy,  0.0 ni, 96.5 id,  0.2 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7963.4 total,   2048.0 free,   3072.0 used,   2843.4 buff/cache
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   4512.0 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   5678 apache    20   0  274448  81920  40960 S   2.5   1.0   0:45.23 httpd
   1234 student   20   0  226524   5432   3500 S   0.3   0.1   0:01.50 bash
      1 root      20   0  171820  13256  10240 S   0.0   0.2   0:03.45 systemd

Interactive Commands:

q - Quit

h - Help

k - Kill a process

r - Renice a process

Sorting:

M - Sort by memory

P - Sort by CPU (default)

T - Sort by time

N - Sort by PID

Understanding Load Average

# View load average
[student@server ~]$ uptime
 10:45:32 up 1 day,  2:30,  2 users,  load average: 0.15, 0.10, 0.05
                                                     1min  5min  15min

# Also visible in top header and /proc/loadavg
[student@server ~]$ cat /proc/loadavg
0.15 0.10 0.05 1/245 9876

# Check number of CPUs
[student@server ~]$ nproc
4

[student@server ~]$ lscpu | grep "^CPU(s):"
CPU(s):                          4
Interpreting Load Average:
  • Load = 1.00 on single CPU = 100% utilized
  • Load = 4.00 on 4 CPUs = 100% utilized
  • Load > CPU count = processes waiting for CPU
  • Compare 1/5/15 minute values to see trends

Introduction to Signals

Signals are software interrupts sent to processes to trigger specific behaviors. They're the primary mechanism for controlling processes.

1
SIGHUP
Hangup - reload configuration
2
SIGINT
Interrupt - Ctrl+C
9
SIGKILL
Kill - force terminate (cannot be caught)
15
SIGTERM
Terminate - graceful shutdown (default)
18
SIGCONT
Continue - resume stopped process
19
SIGSTOP
Stop - pause process (cannot be caught)
20
SIGTSTP
Terminal Stop - Ctrl+Z
3
SIGQUIT
Quit - Ctrl+\ with core dump
# List all available signals
[student@server ~]$ kill -l

The kill Command

# Send SIGTERM (default - graceful termination)
[root@server ~]# kill 5678
[root@server ~]# kill -15 5678
[root@server ~]# kill -SIGTERM 5678
[root@server ~]# kill -TERM 5678

# Send SIGKILL (force kill - use as last resort)
[root@server ~]# kill -9 5678
[root@server ~]# kill -SIGKILL 5678
[root@server ~]# kill -KILL 5678

# Send SIGHUP (reload configuration)
[root@server ~]# kill -1 5678
[root@server ~]# kill -HUP 5678

# Kill multiple processes
[root@server ~]# kill 5678 5679 5680

# Verify process is gone
[root@server ~]# ps aux | grep 5678
⚠ Best Practice: Always try kill (SIGTERM) first. Only use kill -9 (SIGKILL) if SIGTERM doesn't work after a few seconds.

killall and pkill

# killall - kill processes by exact name
[root@server ~]# killall httpd           # SIGTERM to all httpd processes
[root@server ~]# killall -9 httpd        # SIGKILL to all httpd
[root@server ~]# killall -i httpd        # Interactive - confirm each
[root@server ~]# killall -u student      # Kill all processes by user

# pkill - kill processes by pattern (more flexible)
[root@server ~]# pkill httpd             # Pattern match (partial OK)
[root@server ~]# pkill -9 httpd          # SIGKILL
[root@server ~]# pkill -u apache         # Kill processes by user
[root@server ~]# pkill -u apache httpd   # By user AND name
[root@server ~]# pkill -t pts/0          # Kill processes on terminal

# Difference: killall needs exact name, pkill matches patterns
[root@server ~]# killall http            # No match - name must be exact
http: no process found
[root@server ~]# pkill http              # Matches httpd, http-server, etc.
pgrep + kill vs pkill: pgrep -a pattern shows what would match. Use this to verify before running pkill.

Termination Order

Step 1: SIGTERM (15)

Polite request to terminate

↓ Wait a few seconds
Step 2: Check if running

ps or pgrep to verify

↓ Still running?
Step 3: SIGKILL (9)

Force kill - last resort

# Proper termination sequence
[root@server ~]# kill 5678               # SIGTERM - try graceful first
[root@server ~]# sleep 3                 # Give it time to exit
[root@server ~]# pgrep -a 5678 || echo "Process ended"
[root@server ~]# kill -9 5678            # Force kill if still running

Keyboard Signals

Keys Signal Effect
Ctrl+C SIGINT (2) Interrupt - stop the process (can be caught)
Ctrl+Z SIGTSTP (20) Suspend - pause and send to background
Ctrl+\ SIGQUIT (3) Quit - terminate with core dump
# Ctrl+C - Interrupt running command
[student@server ~]$ find / -name "*.conf"
/etc/httpd/conf/httpd.conf
/etc/ssh/sshd_config
^C                                      # User pressed Ctrl+C

# Ctrl+Z - Suspend running command
[student@server ~]$ vim document.txt
[1]+  Stopped                 vim document.txt

# Resume in background or foreground
[student@server ~]$ bg                  # Resume in background
[student@server ~]$ fg                  # Bring to foreground

# Ctrl+\ - Quit (stronger than Ctrl+C)
[student@server ~]$ ./stubborn-program
^\Quit (core dumped)

Job Control

# Run command in background with &
[student@server ~]$ sleep 300 &
[1] 5678                               # Job number and PID

# List current jobs
[student@server ~]$ jobs
[1]+  Running                 sleep 300 &

# Suspend foreground job with Ctrl+Z, then...
[student@server ~]$ vim document.txt
[1]+  Stopped                 vim document.txt

# Resume in foreground
[student@server ~]$ fg
[student@server ~]$ fg %1              # Specify job number

# Resume in background
[student@server ~]$ bg
[student@server ~]$ bg %1

# Kill a job by job number
[student@server ~]$ kill %1

# Multiple background jobs
[student@server ~]$ jobs
[1]   Running                 sleep 300 &
[2]-  Stopped                 vim file.txt
[3]+  Running                 ./script.sh &

Background Processes

# Run in background and redirect output
[student@server ~]$ ./long-script.sh > output.log 2>&1 &
[1] 5678

# Prevent hangup when terminal closes (nohup)
[student@server ~]$ nohup ./long-script.sh &
[1] 5678
nohup: ignoring input and appending output to 'nohup.out'

# nohup with output redirect
[student@server ~]$ nohup ./script.sh > script.log 2>&1 &

# Disown a running job (remove from shell's job table)
[student@server ~]$ ./process &
[student@server ~]$ disown %1

# Start process that survives logout
[student@server ~]$ nohup ./daemon-script.sh &
[student@server ~]$ exit                 # Script continues running

# Alternative: use screen or tmux for persistent sessions
[student@server ~]$ screen -S mysession
[student@server ~]$ ./long-process
# Ctrl+A, D to detach - process keeps running
[student@server ~]$ screen -r mysession  # Reattach later

Process Priority

The nice value influences process scheduling priority. Lower values = higher priority. Range: -20 (highest) to +19 (lowest).

-20 to -1

High Priority
(requires root)

0

Default
(normal processes)

+1 to +19

Low Priority
(background tasks)

# Start process with specific nice value
[student@server ~]$ nice -n 10 ./background-task.sh
[root@server ~]# nice -n -5 ./important-task.sh

# View nice values in ps
[student@server ~]$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000  1234  1200  0  80   0 -  5678 -      pts/0    00:00:00 bash
0 R  1000  5678  1234  0  90  10 -  2345 -      pts/0    00:00:05 background-task

Changing Priority: renice

# Change nice value of running process
[student@server ~]$ renice 10 -p 5678
5678 (process ID) old priority 0, new priority 10

# Set nice value for all processes of a user
[root@server ~]# renice 5 -u student
1000 (user ID) old priority 0, new priority 5

# Increase priority (only root)
[root@server ~]# renice -5 -p 5678
5678 (process ID) old priority 10, new priority -5

# Change priority interactively in top
# Press 'r', enter PID, enter new nice value

# View current nice values
[student@server ~]$ ps -eo pid,ni,comm | head
    PID  NI COMMAND
      1   0 systemd
      2   0 kthreadd
   5678  10 background-task
Remember: Users can only increase nice values (lower priority). Only root can decrease nice values (raise priority).

Process Info in /proc

# /proc contains a directory for each running process
[student@server ~]$ ls /proc
1  1234  2  245  5678  acpi  bus  cmdline  cpuinfo ...

# Examine a specific process
[student@server ~]$ ls /proc/5678
cmdline  cwd  environ  exe  fd  maps  status ...

# View command line that started process
[student@server ~]$ cat /proc/5678/cmdline
/usr/sbin/httpd-DFOREGROUND

# View process status
[student@server ~]$ cat /proc/5678/status | head -10
Name:   httpd
State:  S (sleeping)
Pid:    5678
PPid:   1
Uid:    48      48      48      48
Gid:    48      48      48      48

# View memory map
[student@server ~]$ cat /proc/5678/maps | head

# View open file descriptors
[student@server ~]$ ls -l /proc/5678/fd

Practical Scenarios