RED HAT ENTERPRISE LINUX

Process Management

Monitor and Control Processes in RHEL

CIS126RH | RHEL System Administration 1
Mesa Community College

Learning Objectives

1
Understand processes and their attributes

PIDs, parent/child relationships, states, and ownership

2
Monitor processes with ps and top

View system-wide process information in real time

3
Control foreground and background jobs

Use &, jobs, fg, bg, and nohup effectively

4
Send signals and adjust priority

Use kill, killall, pkill, nice, and renice

What is a Process?

A process is a running instance of a program. Every process has a unique Process ID (PID), is owned by a user, has a parent process, and maintains its own memory space.

Key Attributes

  • PID — unique process identifier
  • PPID — parent process ID
  • UID/GID — running user and group
  • Priority — scheduling importance

Resource Usage

  • %CPU — processor usage
  • %MEM — physical memory
  • VSZ — virtual memory size
  • RSS — resident set size (RAM)

Process States

StateSymbolMeaning
RunningRActively using CPU or in run queue
SleepingSWaiting for an event (interruptible)
Disk SleepDWaiting for I/O (uninterruptible — cannot kill)
StoppedTPaused — Ctrl+Z or SIGSTOP signal
ZombieZTerminated but not reaped by parent
Note: A process in D state (uninterruptible sleep) cannot be killed with SIGKILL while waiting for I/O. This is typically temporary — it resolves when the I/O completes.

Process Hierarchy

# View the process tree
[user@host ~]$ pstree
systemd─┬─NetworkManager───3*[{NetworkManager}]
        ├─agetty
        ├─auditd───{auditd}
        ├─crond
        ├─sshd───sshd───sshd───bash───pstree
        └─systemd-journal

# Show PIDs in the tree
[user@host ~]$ pstree -p
systemd(1)─┬─sshd(1234)───sshd(5678)───sshd(5680)───bash(5681)───pstree(5700)

# Show tree for a specific process
[user@host ~]$ pstree -p 1234
PID 1: systemd is the first process and the parent or ancestor of every other process. When systemd stops, the system shuts down.

Viewing Processes: ps

# Basic ps — shows processes in current terminal
[user@host ~]$ ps
  PID TTY          TIME CMD
 5681 pts/0    00:00:00 bash
 5700 pts/0    00:00:00 ps

# Show all processes (BSD style — most common)
[user@host ~]$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY   STAT START   TIME COMMAND
root         1  0.0  0.3 171820 13256 ?     Ss   09:00   0:02 /usr/lib/systemd/systemd
root         2  0.0  0.0      0     0 ?     S    09:00   0:00 [kthreadd]
apache    1234  0.2  1.5 550000 62000 ?     S    09:15   0:45 /usr/sbin/httpd
ps aux is the standard snapshot for all processes. For a real-time view, use top instead.

ps Output Anatomy

# Unix style — shows PPID (parent PID)
[user@host ~]$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 09:00 ?        00:00:02 /usr/lib/systemd/systemd
student   5681  5680  0 10:30 pts/0    00:00:00 -bash
FieldMeaning
PIDProcess ID — unique identifier
PPIDParent process ID
%CPU / %MEMResource usage percentages
VSZ / RSSVirtual / resident memory (KB)
STATProcess state (R, S, D, T, Z)
TIMECumulative CPU time used

Understanding ps STAT Column

CodeMeaningTypical cause
RRunning or runnableActively computing, in run queue
SSleepingWaiting for input, timer, or event
DUninterruptible sleepWaiting for disk I/O
TStoppedCtrl+Z or SIGSTOP signal
ZZombieFinished but parent not waiting
sSession leaderFirst process in session group

Understanding ps STAT Modifiers

CodeMeaningTypical cause
+Foreground process groupRunning in current terminal
lMulti-threadedMany services use threads
NLow-priority (nice)niceness value greater than 0
<High-priorityniceness value less than 0
IIdle kernel threadKernel worker waiting for work
SsSleeping session leaderSSH daemon, shell process
Example: Ss = sleeping + session leader (typical for SSH connections and terminal shells)

Filtering ps Output

# Find processes by name
[user@host ~]$ ps aux | grep httpd
root      1234  0.0  0.5 275000 20000 ?  Ss  09:15  0:00 /usr/sbin/httpd
apache    1235  0.0  0.3 275500 12000 ?  S   09:15  0:01 /usr/sbin/httpd

# Exclude grep itself from results
[user@host ~]$ ps aux | grep [h]ttpd
# Find by user
[user@host ~]$ ps -u apache

# Custom output — sorted by CPU usage
[user@host ~]$ ps -eo pid,user,%cpu,%mem,cmd --sort=-%cpu | head
  PID USER     %CPU %MEM CMD
 3456 mysql    45.2 12.5 /usr/libexec/mysqld
 1234 apache    8.3  2.1 /usr/sbin/httpd

Real-time Monitoring: top

# Start top (press q to quit)
[user@host ~]$ top

# Start top sorted by memory
[user@host ~]$ top -o %MEM

# Monitor specific PID
[user@host ~]$ top -p 1234

# Monitor multiple PIDs
[user@host ~]$ top -p 1234,5678
top header shows:
load average: — 1, 5, and 15-minute CPU load
%id: — idle CPU percentage (high is good)
MiB Mem/Swap: — memory usage summary

Interactive top Commands

Sorting

PSort by CPU
MSort by memory
TSort by time
RReverse sort order

Actions

kKill a process
rRenice (change priority)
uFilter by user
?Help
qQuit
Practical: Press M to find the biggest memory consumer. Press k then enter the PID to kill a runaway process — all without leaving top.

Other Monitoring Tools — pidof, pgrep

# htop — enhanced interactive viewer (if installed)
[user@host ~]$ htop
# Better visual interface, mouse support, easier to use

# pidof — find PID by exact process name
[user@host ~]$ pidof httpd
1236 1235 1234

# pgrep — search processes by pattern
[user@host ~]$ pgrep -l http
1234 httpd
1235 httpd

# pgrep with full command line
[user@host ~]$ pgrep -a httpd
1234 /usr/sbin/httpd -DFOREGROUND

Other Monitoring Tools — lsof

# lsof — list open files (and sockets) by process
[user@host ~]$ lsof -p 1234 | head

# What process is using a specific file?
[user@host ~]$ lsof /var/log/messages

# What process is listening on a port?
[user@host ~]$ lsof -i :80

# Show all network connections
[user@host ~]$ lsof -i

# Show open files by a user
[user@host ~]$ lsof -u student
lsof (list open files) works for everything: regular files, sockets, pipes, and devices. "In Linux, everything is a file" — lsof shows it all.

Foreground and Background

# Run command in foreground (default) — blocks terminal
[user@host ~]$ sleep 60
# Terminal is blocked for 60 seconds

# Run command in background (add &)
[user@host ~]$ sleep 60 &
[1] 5800      # [job number] PID

# Suspend foreground process (Ctrl+Z)
[user@host ~]$ sleep 60
^Z
[1]+  Stopped                 sleep 60

# Resume in background / bring to foreground
[user@host ~]$ bg
[1]+ sleep 60 &
[user@host ~]$ fg
sleep 60

Managing Jobs

# List current jobs
[user@host ~]$ jobs -l
[1]-  5800 Running                 sleep 100 &
[2]+  5810 Stopped                 vim file.txt

# Bring specific job to foreground by number or name
[user@host ~]$ fg %1           # Job number
[user@host ~]$ fg %vim         # Job start string

# Resume specific job in background
[user@host ~]$ bg %2

# Disown — remove job from shell tracking
[user@host ~]$ disown %1
# Process continues but shell no longer tracks it
+ and -: The + marks the current job (default for fg/bg). The - marks the previous job.

Keeping Processes Running

# nohup — ignore SIGHUP signal (survive logout)
[user@host ~]$ nohup long-running-script.sh &
nohup: ignoring input and appending output to 'nohup.out'
[1] 5850

# Redirect output explicitly
[user@host ~]$ nohup ./backup.sh > backup.log 2>&1 &

# Safe to log out — process continues
[user@host ~]$ exit
# Alternative: screen for interactive long-running sessions
[user@host ~]$ screen -S mysession
# Work inside screen session...
# Detach: Ctrl+A, D
# Reattach later:
[user@host ~]$ screen -r mysession

Understanding Signals

SignalNumberMeaningCan be caught?
SIGHUP1Hangup — reload configYes
SIGINT2Interrupt (Ctrl+C)Yes
SIGQUIT3Quit with core dumpYes
SIGKILL9Force kill — immediateNo
SIGTERM15Graceful terminateYes
SIGSTOP19Pause processNo
SIGCONT18Continue (resume)Yes
SIGUSR1/210/12User-defined signalsYes
Rule: Always try SIGTERM (15) first — it allows graceful shutdown. Only use SIGKILL (9) when SIGTERM fails.

Sending Signals: kill

# Default: send SIGTERM (signal 15)
[root@host ~]# kill 1234

# By name or number
[root@host ~]# kill -SIGTERM 1234
[root@host ~]# kill -15 1234
# Force kill (last resort — cannot be caught)
[root@host ~]# kill -9 1234
[root@host ~]# kill -SIGKILL 1234

# Send to multiple processes
[root@host ~]# kill 1234 1235 1236

# List all available signals
[user@host ~]$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 9) SIGKILL     15) SIGTERM     18) SIGCONT     19) SIGSTOP ...

killall by Name

# killall — kill all processes with exact name
[root@host ~]# killall httpd
# Sends SIGTERM to all processes named exactly "httpd"

# Force kill with specific signal
[root@host ~]# killall -9 httpd
[root@host ~]# killall -SIGHUP httpd     # Reload config

pkill by Pattern

# pkill — kill by pattern (more flexible than killall)
[root@host ~]# pkill http
# Matches any process containing "http"

# pkill by user
[root@host ~]# pkill -u student
# Kill all processes owned by student

# Force kill by user
[root@host ~]# pkill -9 -u baduser

# ALWAYS preview first with pgrep!
[user@host ~]$ pgrep -l http
1234 httpd
1235 httpd
# Then: pkill http
Best practice: Always run pgrep -l pattern first to see what pkill pattern would kill.

Process Priority

Nice values influence scheduling priority. Range: -20 (highest priority) to +19 (lowest priority). Default is 0.

High Priority

Nice = -20 to -1
Gets more CPU time
Root only for negative values

Low Priority

Nice = 1 to 19
Gets less CPU time
Any user can increase niceness

Mnemonic: "Niceness" is how nice you are to other processes. High niceness = kind, yielding. Low niceness = demanding, priority.

nice and renice

# Start process with lower priority (nice value 10)
[user@host ~]$ nice -n 10 ./long-task.sh

# Only root can set negative (high priority)
[root@host ~]# nice -n -5 ./important-task.sh
# Change nice value of running process
[root@host ~]# renice -n 15 -p 1234
1234 (process ID) old priority 0, new priority 15

# Renice all processes owned by a user
[root@host ~]# renice -n 10 -u student

# Regular users can only increase nice (lower priority)
[user@host ~]$ renice -n 5 -p 5678      # OK
[user@host ~]$ renice -n -5 -p 5678     # Denied
renice: failed to set priority for 5678: Permission denied

Best Practices

Do

  • Use top for real-time monitoring
  • Try SIGTERM before SIGKILL
  • Use pgrep before pkill to preview
  • Use nohup for long background tasks
  • Check zombie processes regularly
  • Monitor load average

Avoid

  • kill -9 as first approach
  • pkill with broad patterns
  • Ignoring zombie accumulation
  • Negative nice as regular user
  • Killing without identifying first

Key Takeaways

1

Every process has a PID, parent (PPID), owner, and state. Use ps aux for a snapshot, top for real-time view.

2

Use & for background, Ctrl+Z to suspend, fg/bg to manage. Use nohup to survive logout.

3

Send signals with kill (by PID), killall (by name), or pkill (by pattern). Try SIGTERM first, SIGKILL last.

4

Adjust CPU priority with nice (at launch) and renice (running). Regular users can only lower priority.

Graded Lab

  • Use ps aux to find processes owned by a specific user
  • Start a background job, suspend it, and resume it
  • Use top to identify the highest CPU-consuming process
  • Practice killing processes with SIGTERM then SIGKILL
  • Start a process with nice and observe priority in ps

Next: SSH Security and Key-Based Authentication