Introducing Process Management
Understanding the intricacies of process management is essential for Linux administrators. Every action on a Linux server initiates a process, making it imperative to discern between different types of processes for efficient management. Here are the primary categories of processes:
- Shell Jobs: These are commands initiated from the command line, associated with the active shell. They are also known as interactive processes.
- Daemons: These processes offer services and are typically launched during system boot, often with root privileges.
- Kernel Threads: These are integral components of the Linux kernel and aren’t manageable through conventional tools. However, monitoring kernel threads is crucial for assessing system performance.
Processes can operate with multiple threads, each representing a task that a dedicated CPU can handle. While Linux shells lack tools to manage individual threads directly, thread management is typically handled within the command itself.
To effectively manage processes, understanding their types is paramount. Shell jobs demand a distinct approach compared to processes initiated during system boot.
Managing Shell Jobs
When users execute commands, shell jobs are activated. By default, these jobs run as foreground processes, occupying the terminal until completion. Knowing how to run shell jobs in the foreground or background and managing them is essential for administrators.
Running Jobs in the Foreground and Background
Commands typically run as foreground jobs, monopolizing the terminal until completion. However, for non-interactive processes requiring significant time to execute, running them in the background is beneficial. To achieve this:
- Append
&
to the command to start a job in the background immediately. - Use
fg
to bring the last background job to the foreground. - Employ
Ctrl-Z
to temporarily suspend a job, allowing it to be managed. - Utilize
bg
to resume a suspended job in the background. - Employ
Ctrl-C
to terminate the current job abruptly. - Press
Ctrl-D
to indicate the End Of File (EOF) to the current job, prompting it to cease waiting for additional input.
Managing Shell Jobs
Having an overview of active jobs aids in managing them effectively. The jobs
command provides this overview, displaying background job details, including their job numbers. These job numbers are crucial for executing management tasks using fg
and bg
commands.
Understanding Parent–Child Relations
In Linux, when a process is initiated from a shell, it becomes a child process of that shell. This parent–child relationship is crucial in process management as the parent is responsible for managing the child. Consequently, when a shell is terminated, all processes started from it are also terminated, providing a convenient method to end unnecessary processes. However, processes started in the background are not terminated when the parent shell is killed. To terminate these background processes, the kill
command is required.
Note: In earlier versions of the Bash shell, background processes were terminated when the parent shell was terminated. To prevent this, the nohup
command was used. However, in RHEL 9, this workaround is no longer necessary. If a parent process is killed while the child process remains active, the child process becomes a child of systemd
.
Using Common Command-Line Tools for Process Management
On Linux servers, numerous processes are typically running simultaneously. With potentially over a hundred active processes, issues can arise, necessitating the need to stop non-interactive processes or adjust their priority to allocate more system resources to other processes.
Understanding Processes and Threads
Linux tasks are usually initiated as processes, with one process being capable of spawning multiple worker threads. Utilizing threads is advantageous, especially for heavily loaded processes, as threads can be distributed across different CPUs or CPU cores. While Linux administrators cannot manage individual threads directly, they can manage processes. The relationship between threads within a process is determined by the application’s programmer.
Before delving into process management techniques, it’s essential to distinguish between two types of background processes: kernel threads and daemon processes. Kernel threads are integral to the Linux kernel and are identifiable by their names enclosed in square brackets. Administrators should note that kernel threads cannot be managed, and attempts to adjust their priority or terminate them may require shutting down the entire system.
Using ps
to Get Process Information
The ps
command is commonly used to obtain information about active processes. When used without arguments, it displays processes initiated by the current user. Various options can be used to display different process properties. For a concise summary of active processes, ps aux
is recommended. Alternatively, ps -ef
provides detailed information, including the exact command used to start each process. Additional options, such as ps fax
, reveal hierarchical relationships between parent and child processes.
An important piece of information provided by ps
is the Process ID (PID), which is often required for various tasks. Commands like ps aux | grep [process_name]
or pgrep [process_name]
are commonly used to retrieve the PID of specific processes.
Understanding Process Priorities
On modern Linux systems, resource allocation is managed through cgroups, which define three system slices:
- system: This slice hosts all systemd-managed processes.
- user: This slice accommodates all user processes, including those initiated by the root user.
- machine: An optional slice utilized for virtual machines and containers.
By default, all slices have an equal CPUWeight, meaning CPU capacity is evenly distributed among them during high demand. This egalitarian approach can result in unexpected behavior, particularly in scenarios where system processes are affected by user processes. To manage process priority within a slice, the nice
and renice
commands are employed.
Exploring Relations Between Slices
While not a topic typically covered in the RHCSA exam, understanding how processes within slices are treated is valuable. To observe this behavior:
- Open a root shell and clone the course git repository.
- Copy the stress* files to /etc/systemd/system.
- Reload systemd to apply changes.
- Start stress1 and stress2 services.
- Use
top
to monitor CPU usage, observing that both dd processes receive approximately 50% of CPU capacity. - Open a terminal as a non-root user and run a CPU-intensive command.
- Notice that both dd processes continue to receive 50% of CPU cycles, illustrating the impact of a single user process on system processes.
- If not observed, switch to per-core view in
top
. - Experiment with temporarily disabling CPU cores to observe changes.
- Terminate all dd processes using
killall dd
.
To address potential issues stemming from the default cgroup configuration, increase the priority of the system slice by adjusting its CPUWeight:
systemctl set-property system.slice CPUWeight=800
Managing Process Priorities
Linux processes are initially launched with a specific priority, typically assigned a priority level of 20. Adjustments to default priorities can be made using nice
to start a process with an altered priority or renice
to modify the priority of an existing process. Prioritizing processes is beneficial in scenarios such as:
- Initiating resource-intensive tasks like backups without disrupting other processes.
- Expediting critical computational tasks by allocating more CPU time.
In earlier Linux versions, adjusting process priorities could risk blocking other processes, including vital kernel threads. However, modern kernels mitigate this risk by differentiating between essential kernel threads and user processes. Additionally, the prevalence of multi-core systems prevents single-threaded processes from monopolizing CPU resources.
When adjusting process priority with nice
or renice
, values ranging from -20 to 19 are used, with 0 being the default niceness. Negative values increase priority, while positive values decrease it. It’s advisable to adjust priorities incrementally to assess their impact.
Sending Signals to Processes with kill
, killall
, and pkill
Linux processes maintain hierarchical relationships, where each process has a parent. Killing a parent process in RHEL 9 results in its child processes becoming children of the systemd process, preventing unintended termination.
Several signals can be sent to processes, including:
- SIGTERM (15): Requests a process to stop.
- SIGKILL (9): Forces a process to stop.
- SIGHUP (1): Hangs up a process, prompting it to reread configuration files.
The kill
command is used to send signals to processes, with common usage involving termination via PID. If a process ignores termination requests, kill -9
can be used to force termination, albeit with the risk of data loss.
Commands like killall
and pkill
offer alternatives, with pkill
being user-friendly by accepting process names as arguments. However, caution is advised, as indiscriminate use of these commands can lead to unintended terminations.
Killing Zombies
Zombies are processes that have finished execution but remain listed in the process table. While zombies are typically harmless, they can clutter the system. To address this:
- Clone the books git repository.
- Navigate to the rhcsa directory and start the demo zombie process using
./zombie
. - Verify the zombie process with
ps aux | grep zombie
. - Attempt to kill the zombie’s child process using
kill <childpid>
, which will fail. - Use
kill -SIGCHLD <parentpid>
to instruct the parent process to remove its child processes. The zombie will be adopted by systemd and removed shortly. - If the zombie persists, use
kill -9
to terminate the parent process.
Using top to Manage Processes
The top
utility provides a comprehensive view of active processes, allowing easy identification and management. Key functionalities include adjusting process priority and terminating processes. The process states observed in top are:
- Running (R): Active processes utilizing CPU time or queued for execution.
- Sleeping (S): Processes waiting for an event to complete.
- Uninterruptible sleep (D): Processes in a sleep state, often due to I/O operations.
- Stopped (T): Stopped processes, typically from user intervention.
- Zombie (Z): Processes that have completed but remain in the process table.
From top, you can send signals to processes using k
, with options to specify the signal type. Renicing a process is achieved with r
, where you can adjust the process priority. Additionally, top provides load average information, which indicates system activity levels over time.
Managing Load Average
The load average reflects the number of processes in a runnable or blocking state. It’s recommended that the load average does not exceed the number of CPU cores in the system. To manage load average:
- Open a root shell and initiate CPU-intensive tasks.
- Use
top
to observe the load average. - Check load average statistics with
uptime
. - Determine the number of CPU cores using
lscpu
. - Terminate CPU-intensive processes using
killall dd
.
Using tuned to Optimize Performance
RHEL 9 includes the tuned
daemon for performance optimization. Different profiles are available to balance power consumption and performance. Administrators can manually select profiles or create custom ones. Key profiles include:
- balanced: Balances power usage and performance.
- latency-performance: Optimized for maximum throughput.
- powersave: Focuses on maximum power saving.
To manage performance profiles:
- Install
tuned
if not already installed. - Check
tuned
status withsystemctl status tuned
. - View active profile with
tuned-adm active
. - See recommended profile with
tuned-adm recommend
. - Switch to a desired profile using
tuned-adm profile profile-name
.
These exercises allow for hands-on practice with tuned for performance optimization.
Exercises for Practice:
- Managing Zombie Processes:
- Clone a Git repository and navigate to a directory containing a script to create zombie processes.
- Start the script to create zombie processes.
- Use commands like
ps aux | grep
to identify and verify the presence of zombie processes. - Attempt to terminate the zombie processes using different methods such as
kill
andkill -SIGCHLD
. - Explore what happens when zombie processes are not properly handled.
- Utilizing Top for Process Management:
- Open the
top
utility and familiarize yourself with its interface. - Identify different process states (Running, Sleeping, etc.) and understand their meanings.
- Experiment with sending signals to processes using
k
and adjusting process priority usingr
. - Monitor the load average and understand its significance in system performance.
- Open the
- Load Average Management:
- Initiate CPU-intensive tasks on the system.
- Use commands like
top
,uptime
, andlscpu
to monitor system load and CPU resources. - Determine the relationship between the load average and the number of CPU cores.
- Practice terminating CPU-intensive processes using
killall
.
- Optimizing Performance with Tuned:
- Install the
tuned
daemon if not already installed. - Check the status of the
tuned
daemon usingsystemctl
. - Explore available performance profiles using
tuned-adm list
. - Switch between different profiles using
tuned-adm profile
. - Use
tuned-adm recommend
to identify the recommended profile for the system.
- Install the
- Creating Custom Tuned Profiles (Advanced):
- Research the structure of tuned profiles and how they influence system performance.
- Experiment with creating custom tuned profiles tailored to specific use cases (e.g., high-performance computing, power-saving mode).
- Test the effectiveness of custom profiles in improving system performance and resource utilization.
These exercises provide practical hands-on experience with process management, system performance monitoring, and optimization techniques using tools like top
and tuned
.
Revision: Process Management
Process management in RHEL involves a series of techniques and commands that allow users to monitor, control, and manipulate running processes. Below is an in-depth overview of process management in RHEL.
- Understanding Processes:
- Process: A process is an instance of a running program. Each process in Linux is assigned a unique Process ID (PID).
- Parent Process: Every process, except the init/systemd process, has a parent process.
- Child Process: Processes spawned by other processes are called child processes.
- Foreground Process: A process that is running in the current terminal session and occupies the terminal.
- Background Process: A process that runs independently of the terminal session and doesn’t occupy the terminal.
- Viewing Processes:
- ps Command: Displays information about the currently running processes.
- Examples:
- ps Command: Displays information about the currently running processes.
ps
ps aux
ps -ef
- top Command: Provides a dynamic, real-time view of the running system, including processes.
- Example:
top
- Note: Use ‘h’ for help within top, and ‘q’ to quit.
- htop Command: An enhanced version of top (requires installation).
- Example:
htop
- pgrep Command: Searches for processes based on name and other attributes.
- Example:
pgrep sshd
- pidof Command: Finds the PID of a running program.
- Example:
pidof sshd
- pstree Command: Displays a tree of processes.
- Example:
pstree
- Controlling Processes:
- bg Command: Moves a job to the background.
- Example:
- bg Command: Moves a job to the background.
bg %1
- fg Command: Brings a job to the foreground.
- Example:
fg %1
- jobs Command: Lists the current jobs.
- Example:
jobs
- kill Command: Sends a signal to a process.
- Examples:
kill <PID>
kill -SIGTERM <PID> # Terminate
kill -SIGKILL <PID> # Force kill
kill -SIGSTOP <PID> # Stop (pause)
kill -SIGCONT <PID> # Continue
- killall Command: Kills all processes by name.
- Example:
killall firefox
- nice Command: Starts a process with a modified scheduling priority.
- Example:
nice -n 10 command
- renice Command: Alters the priority of a running process.
- Example:
renice -n 10 -p <PID>
- nohup Command: Runs a command immune to hangups, with output to a non-tty.
- Example:
nohup long_running_command &
- Signals:
- Signals are a limited form of inter-process communication (IPC), used to notify a process that a particular event has occurred.
- Common signals include:
- SIGTERM (15): Terminate the process.
- SIGKILL (9): Forcefully kill the process.
- SIGSTOP (19): Stop the process.
- SIGCONT (18): Continue the stopped process.
- SIGHUP (1): Hang up detected on controlling terminal or death of controlling process.
- Monitoring System Performance:
- vmstat Command: Reports virtual memory statistics.
- Example:
- vmstat Command: Reports virtual memory statistics.
vmstat
- iostat Command: Reports CPU and I/O statistics.
- Example:
iostat
- mpstat Command: Reports CPU usage per processor.
- Example:
mpstat
- sar Command: Collects, reports, or saves system activity information.
- Example:
sar
- Systemd and Managing Services:
- systemctl Command: Controls the systemd system and service manager.
- Examples:
- systemctl Command: Controls the systemd system and service manager.
systemctl status httpd
systemctl start sshd
systemctl stop sshd
systemctl restart httpd
systemctl enable sshd
systemctl disable sshd
systemctl is-active httpd
systemctl is-enabled sshd
- journalctl Command: Queries and displays messages from the journal.
- Examples:
journalctl -xe
journalctl -u sshd
- Service Management with SysVinit (legacy):
- service Command: Controls services on systems using SysVinit.
- Examples:
- service Command: Controls services on systems using SysVinit.
service httpd start
service sshd stop
service httpd restart
service sshd status
- chkconfig Command: Updates and queries runlevel information for system services.
- Examples:
chkconfig httpd on
chkconfig sshd off
By mastering these commands and concepts, you will be well-prepared for managing processes in RHEL.