Why does your Linux system sometimes slow to a crawl, you have no idea which program is causing it, and you need to find and fix it fast—on the EX200 exam? This chapter solves that exact problem: knowing what is running on your system (processes), how to control them, and how to monitor overall system health so you can diagnose performance issues and keep services running reliably.
Jump to a section
A simple way to picture Managing Processes and Monitoring System Activity
A busy restaurant kitchen is a system running at full capacity. The head chef is the system administrator, and each ticket on the rail is a running process—a program executing at that moment. A ticket to cook a steak is a compute-intensive task, while a ticket to plate a salad is a lightweight operation. The chef constantly monitors the pass: which orders are taking too long (identifying high CPU usage), which station has a backlog (indicating high load), and whether the grill is idle while the fryer is overwhelmed (checking resource allocation). When a customer complains their food is cold, the chef checks the specific ticket and decides whether to fire it again (sending a SIGTERM signal to restart) or scrap it entirely (killing the process with SIGKILL). If too many orders pile up, the chef may temporarily pause accepting new tickets (nice value adjustment) to let the kitchen catch up. The expeditor calls out the status of each ticket every 30 seconds, just like the top command refreshes process lists. When the health inspector arrives, the chef can pull up every ticket from the last hour (system logs) to show what was cooked and when. This entire dance of creation, monitoring, prioritisation, and termination is exactly what happens inside a Linux system—the kernel (the head chef) manages thousands of processes every second, ensuring the system stays responsive and no single program eats all the CPU or memory.
A waiter dropping a plate is a process crashing. A backup generator kicking in is systemd restarting a service. The dishwashing station that runs all night without stopping is a daemon process. The chef adjusting the flame under a pot is changing a process priority with renice. Every action in the kitchen maps precisely to a Linux command: ps lists the tickets, top shows the rush, kill cancels a ticket, and systemctl stops and starts whole stations.
Every time you run a command, open an application, or start a service on Linux, you create a process. A process is simply an instance of a running program. Think of a program (like Firefox or a web server) as a recipe written on paper—it sits on the disk, doing nothing. A process is a copy of that recipe being actively cooked in the CPU and memory. The Linux kernel (the core of the operating system) is responsible for managing all these processes: giving each one a turn on the CPU, allocating memory, and ensuring they do not interfere with each other.
Each process is identified by a unique numeric ID called the Process ID (PID). The very first process started by the kernel when the system boots is systemd (PID 1). systemd is the mother of all processes—it starts and manages every other process, including services like the SSH server, the web server, and the login manager.
Let us look at how processes are created. A new process is always spawned (created) from an existing parent process through a system call called fork. When you type a command in the terminal, the shell (the command interpreter, like bash) forks itself to create a child process, and that child process then executes the command you typed. This parent-child relationship is hierarchical: every process except systemd has a parent process, identified by the Parent Process ID (PPID).
You can see all running processes using the ps command. Running just ps gives you only the processes in your current terminal. To see every process on the system, use ps aux. Let us break down what these flags mean: a means all processes from all users, u shows the user who owns each process, and x includes processes not attached to a terminal (like daemons). The output shows columns such as USER (who owns the process), PID, %CPU (percentage of CPU usage), %MEM (percentage of RAM usage), VSZ and RSS (virtual and physical memory sizes), STAT (process state—R for running, S for sleeping, D for uninterruptible sleep, Z for zombie), START (when it started), TIME (cumulative CPU time used), and COMMAND (the command that started it).
A more dynamic and continuously updating view is given by the top command. top shows a real-time list of processes sorted by CPU usage by default, updating every few seconds. You can sort by memory using M, kill a process by pressing k and entering its PID, and change the nice value (priority) by pressing r and entering a new value. The header of top displays critical system information:
uptime (how long the system has been running)
load average (three numbers showing system load over the last 1, 5, and 15 minutes)
number of tasks (total, running, sleeping, stopped, zombie)
CPU usage breakdown (us for user processes, sy for system/kernel processes, id for idle, wa for waiting on I/O, st for stolen by virtual machine)
Memory usage (total, free, used, buff/cache)
Swap usage (total, free, used, avail Mem)
A zombie process is a process that has finished execution but still has an entry in the process table because its parent has not yet read its exit status. Zombies consume minimal resources but indicate a bug in the parent process. A daemon is a background process that runs continuously, not connected to any terminal—examples include httpd (web server), sshd (SSH server), and crond (scheduler).
Now, how do you send signals to processes? The kill command does exactly what its name suggests—it sends a signal to a process. By default, kill sends SIGTERM (signal 15), which asks the process to terminate gracefully. If a process ignores SIGTERM, you can send SIGKILL (signal 9), which forces immediate termination and cannot be caught or ignored by the process. Other common signals include SIGHUP (signal 1, often used to reload configuration), SIGSTOP (signal 19, pauses execution), and SIGCONT (signal 18, resumes execution). Use kill -l to list all available signals.
To change the priority of a running process, you use the renice command. The priority is called the nice value, which ranges from -20 (highest priority) to +19 (lowest priority). A process with a nice value of -5 gets more CPU time than a process with a nice value of +10. Only the root user can set negative nice values. When starting a new process with a specific nice value, use nice -n [value] command.
Finally, how does the system manage processes when they have finished but their parent has not collected their exit code? They become zombie processes. Regularly check for zombies using ps aux | grep 'Z' to catch those rare situations. If you see a zombie, identify its parent PID and decide whether to restart the parent process to clean it up.
List all running processes
Open a terminal and run ps aux. This shows every process on the system with its PID, CPU and memory usage, owner, and command. This is the first step in diagnosing any system issue—you need to see what is running before you can control it.
Identify the process causing high resource usage
Run top to see processes sorted by CPU usage in real time. Look at the %CPU and %MEM columns. If a process is consuming an abnormal amount (e.g., 95% CPU for a simple script), note its PID. Also check the load average line: if the 1-minute load is higher than the 5-minute load, the system is getting busier.
Investigate the suspicious process
Use ps -fp [PID] to see full details of the process, including the exact command line and the parent PID (PPID). This helps you understand whether the process is legitimate (part of a known service) or potentially malicious. Use pstree -p to see where this process sits in the process hierarchy.
Stop the problematic process gracefully
Send a SIGTERM signal using kill [PID] (or kill -15 [PID]). Check top again after a few seconds. If the process no longer appears, it has terminated cleanly. If it is still there, try kill -1 (SIGHUP) to reload its configuration. Only use kill -9 (SIGKILL) if the process remains unresponsive.
Handle a zombie process if one appears
If after killing a process you see a 'Z' in the STAT column of ps aux, you have a zombie. Identify its parent PID from the PPID column. Send SIGHUP (kill -1 PPID) to the parent process, or restart the parent service using systemctl restart [service]. The zombie will be cleaned up automatically.
Adjust process priority if needed
If a critical service like a web server needs more CPU time under heavy load, use renice -n -5 -p [PID] to give it higher priority. Verify the change with top (look at the NI column). Remember: only root can lower the nice value (make a process more important).
Monitor system health over time
Use uptime to see the current load averages. Use free -h to check memory and swap usage. Use journalctl -xe to review recent system log messages for errors. Regularly running these commands helps you catch problems early. For continuous monitoring, consider saving top snapshots to a log file.
Imagine you work as a junior Linux administrator for a mid-size e-commerce company that runs its website on a Red Hat Enterprise Linux (RHEL) server. It is the day of a big flash sale, and customers are flooding the site. Suddenly, your monitoring system alerts you that the web server is unresponsive.
You SSH into the server (remote access via the command line) and immediately run the top command. The top screen shows that CPU usage is at 95%, and the process at the top of the list is httpd (the Apache web server), chewing up 80% of the CPU. But you also see a second process named perl that is using 15% CPU and 4GB of memory—something unusual, as the site does not run Perl scripts normally. This process is owned by a user apache, which suggests a misconfigured CGI script might have gone haywire.
You decide to investigate the suspicious process. Noting its PID (say 7890), you check its full command line path using ps -fp 7890. It shows /usr/bin/perl /var/www/cgi-bin/broken-script.cgi. You confirm with your lead that this script is not part of the sale, so you decide to stop it. You gently kill it with kill -15 7890 (SIGTERM). After a few seconds, you check top again—the process is still there but now in a zombie state. This means the parent process (Apache, PID 1234) has not cleaned it up. You send SIGHUP to Apache: kill -1 1234, which reloads Apache and clears the zombie. The CPU drops back to 20%.
But the sale continues, and load increases. You now want to ensure the web server gets more CPU priority than other services like the backup script that runs on the same server. You use renice -n -5 -p 1234 to give the web server a higher priority. You also check memory usage using free -h (human-readable). You see only 500MB free—close to swap usage. You identify another process consuming too much RAM and decide to delay a non-critical service using systemctl stop some-daemon.service.
Later, you need to analyse historical performance. You check the system log /var/log/messages and use journalctl -xe to see recent boot messages and errors. You also set up a cron job to collect top output every hour into a log file for future analysis.
Finally, you want to see the entire process tree. You run pstree, which shows systemd at the root, then branches like sshd, httpd, crond, and bash. This visualises which parent processes own which children and helps you understand the relationship between services.
Key tools you used: - top: real-time monitoring - ps aux: listing all processes - kill: sending signals - renice: adjusting priority - free: checking memory - systemctl: controlling systemd services - journalctl: viewing logs - pstree: visualising the process hierarchy
The EX200 exam tests your ability to manage processes and monitor system activity through multiple-choice questions, performance-based tasks (where you fix a live server), and scenario-based questions. The exam loves to set traps around signal numbers and their meanings.
Key topics tested:
Using ps to list processes with correct options (especially ps aux, ps -ef, and understanding the difference)
Interpreting the output of top, especially load average, zombie count, and CPU states (us, sy, id, wa, st)
Sending signals with kill: you must memorise that SIGTERM (15) is the default, SIGHUP (1) reloads config, SIGKILL (9) is the nuclear option, and SIGSTOP (19) pauses
Using killall to kill processes by name (e.g., killall -9 httpd)
Using pkill to kill processes by pattern (e.g., pkill -f 'perl')
Changing process priority with nice and renice: knowing that root can set negative values, and that higher nice value means lower priority
Managing background and foreground jobs: putting a process in the background with &, bringing it to foreground with fg, listing jobs with jobs
Understanding zombie processes: what causes them, how to identify them (ps aux | grep Z), and how to clean them (fixing or restarting the parent)
Understanding daemons: processes that run in the background and are usually managed by systemd (systemctl status, start, stop, restart)
Using uptime and /proc/loadavg to check system load
Using free to check memory and swap usage
Using journalctl to view system logs
Common exam traps:
They might ask: 'Which signal is sent by default when you run kill 1234?' The answer is SIGTERM (15), not SIGKILL.
They might show a top output with a high load average but low CPU usage—this indicates I/O wait, not CPU bottleneck.
They might ask: 'What command shows the parent-child relationship of processes?' Answer: pstree or ps -ef --forest.
They might give a scenario where a zombie process appears and ask for the first step to resolve it. The answer is to identify the parent PID and send it a signal or restart it, not to kill the zombie directly.
They might test the difference between nice and renice: nice sets priority when starting a process, renice changes it for a running process.
Commands you must memorise for the exam: - ps aux - ps -ef - top - kill [signal] PID - killall [signal] [name] - pkill [pattern] - renice -n [value] -p [PID] - nice -n [value] command - jobs, fg, bg - uptime - free -h - journalctl -xe - systemctl status/start/stop/restart [service] - pstree
Every running command or program is a process with a unique numeric ID called a PID.
Use ps aux to see every process on the system, including background daemons and processes owned by other users.
The default signal sent by kill without an option is SIGTERM (15), which asks a process to terminate gracefully.
SIGKILL (signal 9) forcefully terminates a process and should be used only when a process ignores SIGTERM.
A zombie process is a finished process whose parent has not read its exit status; it cannot be killed and requires fixing the parent.
The nice value of a process ranges from -20 (highest priority) to +19 (lowest priority); only root can set negative values.
Load average in top shows the number of processes waiting for CPU or I/O over 1, 5, and 15 minutes.
Use renice -n value -p PID to change the priority of an already running process.
Daemons are background processes that run continuously, managed by systemd commands like systemctl status.
The pstree command visualises the parent-child hierarchy of all running processes, starting from systemd (PID 1).
These come up on the exam all the time. Here's how to tell them apart.
SIGTERM (signal 15)
Asks the process to terminate gracefully
Can be caught or ignored by the process
Allows the process to save data and close files
SIGKILL (signal 9)
Forces immediate termination without cleanup
Cannot be caught or ignored by the process
May cause data loss or corruption
ps aux
Shows a static snapshot of processes at a single moment
Runs once and exits
Easier to grep and filter output
top
Provides a dynamic, real-time updating view of processes
Continues running until you press q
Includes system summary header (load, CPU, memory)
nice
Sets the priority of a process when it is first launched
Used before the process starts running
Syntax: nice -n value command
renice
Changes the priority of a process that is already running
Used on an active process by PID
Syntax: renice -n value -p PID
killall
Kills processes by exact process name
Does nothing if no process matches exactly
Cannot use regular expressions
pkill
Kills processes by matching a pattern in the name
More flexible—kills partial matches
Supports regular expressions and advanced filtering
systemctl stop
Sends SIGTERM first, then SIGKILL after timeout
Managed by systemd with logging and dependency handling
Preferred for stopping system services
kill -9
Sends SIGKILL immediately with no timeout
Not integrated with systemd's service management
Used only as a last resort for unresponsive processes
Mistake
If I use kill -9 on a process, it will cleanly save its data and exit like a regular shutdown.
Correct
SIGKILL (signal 9) forcefully terminates a process immediately without allowing it to save data, close files, or release resources cleanly. It should only be used as a last resort when a process ignores SIGTERM (signal 15) and hangs.
Movies and TV shows often portray 'kill' as a clean termination button. Beginners assume '9' is just a stronger version of termination, not realising it is a forced, unclean exit that can corrupt data.
Mistake
A high load average always means the CPU is at 100% and is the bottleneck.
Correct
Load average is the number of processes waiting for CPU time OR waiting for I/O (disk, network). A high load average can result from a spinning disk or a slow network filesystem, even if the CPU is mostly idle. Always check the 'wa' (I/O wait) column in top.
The term 'load average' sounds CPU-centric, so beginners naturally associate it only with CPU utilisation. Many do not know that processes waiting for disk I/O also contribute to load.
Mistake
Zombie processes are dangerous and consume significant CPU and memory resources, so they must be killed immediately.
Correct
A zombie process uses almost no system resources—only a small entry in the process table. The real problem is that its parent process is buggy and not reading its exit status. Killing the zombie directly is impossible; you must fix or restart the parent.
The name 'zombie' evokes something scary and dangerous. Beginners think they are actively harmful, like a virus, and try to kill them with kill -9, which has no effect on a zombie.
Mistake
The nice value directly gives a process more or less CPU time in a guaranteed, fixed percentage.
Correct
The nice value is a hint to the kernel's scheduler about priority—it does not guarantee a fixed amount of CPU time. A process with a very low nice value can still be starved of CPU if other processes monopolise it. It is a relative adjustment, not an absolute reservation.
The word 'priority' suggests a concrete, guaranteed slice of CPU. Beginners do not understand that Linux's Completely Fair Scheduler (CFS) uses nice values to determine the proportion of CPU time, but real-world behaviour depends on the number of competing processes.
Mistake
Running 'systemctl stop httpd' immediately kills the httpd process in the same way as 'kill -9 httpd'.
Correct
systemctl stop sends a SIGTERM (signal 15) to the main process of the service, allowing it to shut down gracefully (saving data, closing connections). If the service does not stop after a timeout, systemd then sends SIGKILL. It is a managed, gradual stop, not an instant kill.
The word 'stop' sounds absolute. Beginners assume it means 'immediately cease all activity', like flipping a switch.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
Both list all processes on the system. ps aux uses the BSD-style syntax and shows more columns like %CPU and %MEM by default. ps -ef uses the standard Unix syntax and shows fewer columns. For the EX200 exam, you should be comfortable with both, but ps aux is more commonly used for monitoring.
Use killall [processname] to kill all processes with that exact name, or pkill [pattern] to kill processes matching a pattern (useful when the name varies). For example, killall httpd kills all Apache processes.
A zombie process will have a 'Z' in the STAT column of ps aux. It will also show a command name enclosed in square brackets like [httpd] <defunct>. It consumes very little resources but indicates a parent process that is not collecting exit status.
This usually means the system is waiting for I/O (disk or network). Check the 'wa' line in the CPU section of top—if it is high, the bottleneck is disk or network, not the CPU. Use iostat or iotop to examine disk activity.
Yes, use renice -n [new_value] -p [PID]. For example, renice -n -5 -p 1234 gives PID 1234 a higher priority. Remember that only root can assign negative nice values (higher priority).
Run pstree to see a tree diagram of all processes. Alternatively, use ps -ef --forest to see a forest-like view. This helps you understand which service owns which child processes.
SIGTERM (signal 15) asks a process to terminate gracefully, allowing it to save data and close files. SIGKILL (signal 9) forces immediate termination without any cleanup—the process cannot block or ignore it. Always try SIGTERM first, then SIGKILL if the process hangs.
You've finished Managing Processes and Monitoring System Activity. Continue through the EX200 study guide to build a complete picture of the exam.
Done with this chapter?