As Linux system administrators, developers, or even just power users, we often think of the operating system as a coherent, unified entity. But beneath the surface, Linux is a bustling metropolis of activity, a dynamic collection of running programs and services, each performing its duty. These individual instances of running programs are what we call processes. Understanding how to view, manage, and control these processes is not just a technical skill; it’s an art form that allows us to fine-tune system performance, troubleshoot unresponsive applications, and ensure overall stability.


Table of Contents


What is a Process?

Before we dive into the commands, let’s clarify what a process truly is. Imagine you click an icon to launch a web browser, or you type ls -l in your terminal. Each of these actions initiates a program. Once a program begins execution, it becomes a process. Every process is a self-contained environment with its own memory space, resources, and execution path.

A key concept we quickly learn is the Process ID (PID). Every process on a Linux system is assigned a unique positive integer PID. This PID is like a social security number for a process – it allows us to uniquely identify and interact with it. We’ll see how crucial PIDs are when we need to terminate, inspect, or adjust the priority of a specific process.

os-1 Figure 1: Process Management in Linux


Another vital concept is the Parent Process ID (PPID). Except for the very first process (usually systemd or init, with PID 1), every process on a Linux system is started by another process. The process that initiates another is called its “parent,” and the new process is its “child.” This creates a hierarchical tree structure of processes, which can be incredibly useful for understanding how applications are spawned and related.

Our initial understanding of processes might be abstract, but as we begin to monitor them, we realize that process management is the very heartbeat of a Linux system.


Viewing Processes

The first step in managing processes is being able to see what’s running. Linux provides several powerful utilities for this, each offering a different perspective.

1. ps: The Snapshot Taker

The ps (process status) command is our go-to for taking a snapshot of current processes. It’s not interactive; it just displays information about selected processes and then exits. We use various options to filter and format its output.

  • ps aux – The Universal View: This is probably the most commonly used ps command combination. It’s a lifesaver for getting a comprehensive overview of all running processes on the system.
    • a: Show processes for all users.
    • u: Display user/owner information for each process.
    • x: Show processes not associated with a terminal (daemon processes).

    When we run ps aux, the output is typically formatted into columns:

    • USER: The user ID of the process owner.
    • PID: The unique Process ID.
    • %CPU: CPU utilization percentage.
    • %MEM: Memory utilization percentage.
    • VSZ: Virtual memory size (in KiB).
    • RSS: Resident Set Size (physical memory used, in KiB).
    • TTY: The controlling terminal (usually ? for daemons).
    • STAT: Process status (e.g., R for running, S for sleeping, Z for zombie, T for stopped).
    • START: Time the process started.
    • TIME: Cumulative CPU time.
    • COMMAND: The command that started the process.

example :

```bash
[ganesh@Ganesh-PC /]$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2776  1952 hvc0     Sl+  06:56   0:00 /init
root         7  0.0  0.0   2776     4 hvc0     Sl+  06:56   0:00 plan9 --control-socket 6 --log-level 4 --server-fd 7 --pipe-
root        10  0.0  0.0   2784   208 ?        Ss   06:56   0:00 /init
root        11  0.0  0.0   2784   216 ?        R    06:56   0:00 /init
ganesh      12  0.1  0.0   7480  4336 pts/0    Ss   06:56   0:00 -bash
ganesh      44  0.0  0.0   9944  3476 pts/0    R+   06:56   0:00 ps aux
```


We often pipe ps aux to grep to find specific processes: ps aux | grep nginx.

    [ganesh@Ganesh-PC /]$ ps aux | grep nginx
    ganesh      46  0.0  0.0   6384  2084 pts/0    S+   06:59   0:00 grep --color=auto nginx


  • ps -u username – User-Specific Processes: When we need to see what a particular user is running, this option is invaluable.
      ps -u jane
    

    This shows all processes owned by the user jane.

  • ps -C processname – By Command Name: Sometimes we know the name of the executable and want to see all instances of it.
      ps -C apache2
    

    This is much cleaner than piping to grep if we only want to see processes strictly named apache2.


2. pgrep: Finding PIDs by Name

When we need just the PID(s) of a process based on its name, pgrep is our friend. It returns only the PIDs, which can be incredibly useful for scripting.

pgrep sshd

This will output one or more PIDs corresponding to the sshd daemon.

3. pidof: Exact Program PID

Similar to pgrep, pidof finds the PID of a running program, but it’s often more specific, typically returning the PID of the first instance found.

pidof firefox

We often use pidof when we’re reasonably sure there’s only one instance of a specific program running.


Managing Processes

Once we can identify processes, the next step is to control them. This involves sending signals, altering priorities, and moving them between foreground and background.

1. kill: Sending Signals to Processes

The kill command might sound aggressive, but it’s actually about sending “signals” to processes. The default signal is SIGTERM (15), which politely asks a process to shut down, allowing it to perform cleanup tasks before exiting.

  • kill PID – Graceful Termination:
      kill 12345
    

    We use this as our first attempt to stop an unresponsive process. Most well-behaved applications will gracefully terminate.

  • kill -9 PID – Forceful Termination (SIGKILL): When a process is truly stuck and ignoring SIGTERM, we resort to SIGKILL (signal 9). This signal cannot be caught or ignored by the process, forcing it to terminate immediately without any cleanup.
      kill -9 12345
    

    Caution: We use -9 only as a last resort, as it can lead to data corruption if the process was in the middle of writing data to disk.


2. pkill: Killing by Name (Multiple Instances)

When we want to terminate all instances of a process by its name, pkill is more convenient than finding all PIDs with pgrep and then looping through them with kill.

  • pkill processname – Graceful kill by name:
      pkill firefox
    

    This will send SIGTERM to all firefox processes.

  • pkill -9 processname – Forceful kill by name:
      pkill -9 apache2
    

    This will send SIGKILL to all apache2 processes. Again, use with caution.


3. Stopping and Resuming: SIGSTOP and SIGCONT

Sometimes, we don’t want to terminate a process, but simply pause it temporarily. This is achieved with SIGSTOP and SIGCONT.

  • kill -STOP PID – Pause a Process:
      kill -STOP 54321
    

    The process will halt its execution. It won’t consume CPU cycles but will remain in memory. We might use this to momentarily free up CPU for a critical task or to debug a process in a suspended state.

  • kill -CONT PID – Resume a Process:
      kill -CONT 54321
    

    This signal resumes a stopped process.


4. Adjusting Priority: nice and renice

In a multi-user, multi-tasking environment, CPU time is a shared resource. We can influence how much CPU time a process gets by adjusting its “niceness” value. The “niceness” value ranges from -20 (highest priority, least nice) to 19 (lowest priority, most nice). A default niceness is 0.

  • nice -n 10 command – Launching with Lower Priority: When we start a new command that we know might be resource-intensive but not time-critical (e.g., a long compilation or a backup job), we can launch it with a lower priority.
      nice -n 10 tar -zcvf /backup/archive.tar.gz /var/www/html &
    

    The & sends it to the background immediately. This command will start with a niceness of 10, meaning it will yield CPU time to processes with higher or equal priority.

  • renice -n 10 -p PID – Lowering Priority of a Running Process: If a running process starts consuming too much CPU, we can lower its priority.
      renice -n 10 -p 98765
    

    This makes the process “nicer” to other processes.

  • renice -n -5 -p PID – Increasing Priority (Requires Root): Only the root user can increase the priority (make the niceness value more negative). A non-root user can only lower the priority of their own processes.
      sudo renice -n -5 -p 12345
    

    We use this for critical system processes that need to respond quickly.


Orchestrating Execution

When working in the terminal, we often need to manage processes interactively, especially long-running commands.

  • command & – Run in Background: The simplest way to start a command in the background is to append an ampersand (&) at the end of the command.
      my_long_script.sh &
    

    The shell will immediately return the prompt, and the script will run in the background. We’ll see a job number and the PID.

  • jobs – List Background Jobs: To see what processes we’ve sent to the background in the current shell session, we use jobs.
      jobs
    

    Output might look like: [1]- Running my_long_script.sh & where [1] is the job number.

  • fg %jobnumber – Bring to Foreground: If we need to interact with a background job (e.g., provide input or see its real-time output), we bring it back to the foreground using fg (foreground) and its job number.
      fg %1
    

    The job associated with job number 1 will move to the foreground.

  • Ctrl + Z – Suspend a Running Process: What if a process is already running in the foreground and we need to pause it? We press Ctrl + Z. This sends a SIGSTOP signal to the process, suspending it and returning us to the shell prompt.
      # (running some command, e.g., 'sleep 60')
      ^Z
      [1]+  Stopped                  sleep 60
    
  • bg %jobnumber – Resume Suspended in Background: After suspending a process with Ctrl + Z, we can resume it in the background using bg (background).
      bg %1
    

    The sleep 60 command will now continue running, but in the background.

This job control mechanism is incredibly powerful for interactive terminal sessions, allowing us to multitask without opening multiple terminal windows.


Monitoring System Processes

While ps gives us a snapshot, sometimes we need a dynamic, real-time view of our system’s performance and process activity.

1. top: The Classic Interactive Monitor

top is an indispensable tool for interactive, real-time process monitoring. When we run it, it displays a constantly updated list of processes, sorted by CPU usage by default.

top

The top section of top shows overall system statistics: uptime, number of users, load average, CPU usage, memory usage (physical and swap), and the total number of tasks (processes) with their status.

Key interactive commands within top:

  • k: Kill a process (prompts for PID and signal).
  • r: Renice a process (prompts for PID and new niceness).
  • P: Sort by CPU usage (default).
  • M: Sort by memory usage.
  • T: Sort by running time.
  • q: Quit top.
  • z: Highlight running processes in color.
  • 1: Show CPU usage per core.


top - 07:01:52 up 5 min,  0 users,  load average: 0.00, 0.00, 0.00
Tasks:   6 total,   1 running,   5 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7795.2 total,   7352.0 free,    495.4 used,    154.4 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   7299.8 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                
    1 root      20   0    2776   1952   1828 S   0.0   0.0   0:00.00 init(rhel9wsl)                                         
    7 root      20   0    2776      4      0 S   0.0   0.0   0:00.00 init                                                   
   10 root      20   0    2784    208     80 S   0.0   0.0   0:00.00 SessionLeader                                          
   11 root      20   0    2784    216     80 S   0.0   0.0   0:00.01 Relay(12)                                              
   12 ganesh    20   0    7480   4340   3620 S   0.0   0.1   0:00.04 bash                                                   
   47 ganesh    20   0   10192   3864   3284 R   0.0   0.0   0:00.00 top  


We use top constantly for quickly diagnosing performance bottlenecks, identifying runaway processes, and monitoring system health.

2. htop: The User-Friendly Alternative

While top is powerful, its interface can be a bit arcane for some. htop is a modern, user-friendly, and more interactive alternative. It’s not usually installed by default, but it’s a staple in our toolkits.

  • Installation (Debian/Ubuntu): sudo apt install htop
  • Installation (RHEL/CentOS): sudo yum install htop or sudo dnf install htop
htop

htop offers:

  • Clearer, color-coded output.
  • Mouse support for selecting and interacting with processes.
  • Easier sorting and filtering.
  • Graphical meters for CPU, memory, and swap.
  • Function keys for common actions like F3 (search), F4 (filter), F9 (kill), F10 (quit).

For day-to-day interactive monitoring, htop is often our preferred choice due to its superior usability.


The Unseen Workers: Daemon Process Management with systemctl

Many critical services on a Linux system run as “daemons” – background processes that start at boot and perform specific tasks (e.g., web server, database, SSH server). On modern Linux distributions using systemd, systemctl is our primary command for managing these services.

  • systemctl list-units --type=service – List All Daemons: This command shows all loaded systemd service units and their current status.
      systemctl list-units --type=service
    

    We use this to see which services are active, inactive, enabled at boot, or failed.

  • systemctl start service-name – Start a Service:
      sudo systemctl start apache2
    

    This initiates the apache2 service.

  • systemctl stop service-name – Stop a Service:
      sudo systemctl stop apache2
    

    This gracefully terminates the apache2 service.

  • systemctl restart service-name – Restart a Service:
      sudo systemctl restart apache2
    

    This is equivalent to stop then start.

  • systemctl enable service-name – Enable at Startup: By default, starting a service doesn’t mean it will automatically restart after a reboot. We use enable to ensure a service starts automatically at system boot.
      sudo systemctl enable apache2
    

    This creates symbolic links in the appropriate runlevel directories.

  • systemctl disable service-name – Disable at Startup:
      sudo systemctl disable apache2
    

    This prevents a service from starting at boot.

  • systemctl status service-name – Check Service Status:
      systemctl status apache2
    

    This provides detailed information about a service, including its current status, PID, and recent log entries. This is often our first troubleshooting step when a service isn’t behaving as expected.


Conclusion

Process management is a foundational skill for anyone serious about working with Linux. From understanding the humble PID to wielding the power of kill -9, or carefully tuning resource allocation with nice and renice, our ability to control processes directly impacts system performance, stability, and security.

The commands we’ve explored today—ps, pgrep, pidof, kill, pkill, nice, renice, top, htop, and systemctl—form a comprehensive toolkit. Each has its specific strengths and use cases, and together, they allow us to observe the unseen symphony of running programs, identify rogue performers, bring order to chaos, and ultimately, ensure our Linux systems operate at their peak. It’s a continuous learning process, but one that provides immense satisfaction as we gain ever-finer control over our digital environments.


Stuck ?
Video Tutorial



home