Linux Pattern-Based Killing

LinuxLinuxBeginner
Practice Now

Introduction

In Linux systems, effectively managing processes is crucial for maintaining system stability and performance. While the kill command allows process termination using a specific Process ID (PID), there are situations where you need to terminate multiple processes based on patterns. This is where the pkill command becomes invaluable.

This lab focuses on using the pkill command to terminate processes based on their names, arguments, or other criteria. You will learn how to identify running processes, terminate them selectively using pattern matching, and verify the results of your operations. These skills are essential for system administration and troubleshooting in Linux environments.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) linux(("Linux")) -.-> linux/TextProcessingGroup(["Text Processing"]) linux(("Linux")) -.-> linux/ProcessManagementandControlGroup(["Process Management and Control"]) linux(("Linux")) -.-> linux/SystemInformationandMonitoringGroup(["System Information and Monitoring"]) linux/BasicFileOperationsGroup -.-> linux/chmod("Permission Modifying") linux/TextProcessingGroup -.-> linux/grep("Pattern Searching") linux/ProcessManagementandControlGroup -.-> linux/pkill("Pattern-Based Killing") linux/SystemInformationandMonitoringGroup -.-> linux/ps("Process Displaying") subgraph Lab Skills linux/chmod -.-> lab-271359{{"Linux Pattern-Based Killing"}} linux/grep -.-> lab-271359{{"Linux Pattern-Based Killing"}} linux/pkill -.-> lab-271359{{"Linux Pattern-Based Killing"}} linux/ps -.-> lab-271359{{"Linux Pattern-Based Killing"}} end

Understanding Process Management and Basic Process Termination

In this first step, we'll explore how to identify running processes and terminate them using basic pattern matching. Linux provides several commands for process management, including ps, pgrep, and pkill.

Creating Test Processes

Let's start by creating a simple script that we can run as a background process. We'll create multiple instances of this script to simulate a scenario where you need to terminate several similar processes.

First, navigate to the project directory and create a script called rogue_app.sh:

cd ~/project
nano rogue_app.sh

Add the following content to the script:

#!/bin/bash
while true; do
  echo "Process running with PID $$"
  sleep 5
done

This script runs an infinite loop, printing its Process ID (PID) every 5 seconds.

Now, make the script executable:

chmod +x ~/project/rogue_app.sh

Let's run multiple instances of this script in the background:

for i in {1..5}; do
  ~/project/rogue_app.sh &
done

The & at the end of the command runs each script instance in the background, allowing you to continue using the terminal.

Viewing Running Processes

To see the processes you've just started, use the ps command with appropriate flags:

ps aux | grep rogue_app.sh

The output will look similar to this:

labex     12345  0.0  0.0   2308   580 pts/0    S    10:00   0:00 /bin/bash /home/labex/project/rogue_app.sh
labex     12346  0.0  0.0   2308   580 pts/0    S    10:00   0:00 /bin/bash /home/labex/project/rogue_app.sh
labex     12347  0.0  0.0   2308   580 pts/0    S    10:00   0:00 /bin/bash /home/labex/project/rogue_app.sh
labex     12348  0.0  0.0   2308   580 pts/0    S    10:00   0:00 /bin/bash /home/labex/project/rogue_app.sh
labex     12349  0.0  0.0   2308   580 pts/0    S    10:00   0:00 /bin/bash /home/labex/project/rogue_app.sh
labex     12350  0.0  0.0   2432   584 pts/0    S+   10:00   0:00 grep --color=auto rogue_app.sh

Note that the actual PIDs (the numbers in the second column) will be different on your system.

Terminating Processes with pkill

Now, let's use the pkill command to terminate all instances of our script:

pkill -f rogue_app.sh

The -f option tells pkill to match against the full command line, not just the process name. This is important because when a script runs, the process name is often the interpreter (like /bin/bash) rather than the script name.

Verify that all instances of the script have been terminated:

ps aux | grep rogue_app.sh

You should now only see the grep command itself in the output:

labex     12351  0.0  0.0   2432   584 pts/0    S+   10:01   0:00 grep --color=auto rogue_app.sh

This confirms that all instances of rogue_app.sh have been successfully terminated.

Selective Process Termination with Pattern Matching

In real-world scenarios, you often need to be more selective about which processes to terminate. The pkill command allows you to use pattern matching to target specific processes based on various criteria.

Creating Processes with Different Arguments

Let's create a new script that we'll run with different command-line arguments:

cd ~/project
nano service_worker.sh

Add the following content to the script:

#!/bin/bash
while true; do
  echo "Running service worker with argument: $1"
  sleep 5
done

Make the script executable:

chmod +x ~/project/service_worker.sh

Now, let's run multiple instances of this script with different arguments:

~/project/service_worker.sh normal &
~/project/service_worker.sh normal &
~/project/service_worker.sh --malfunctioning &
~/project/service_worker.sh --malfunctioning &
~/project/service_worker.sh emergency &

This creates five background processes: two "normal" workers, two "malfunctioning" workers, and one "emergency" worker.

Viewing Processes with Different Arguments

Check the running processes:

ps aux | grep service_worker.sh

You should see output similar to:

labex     12360  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh normal
labex     12361  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh normal
labex     12362  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh --malfunctioning
labex     12363  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh --malfunctioning
labex     12364  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh emergency
labex     12365  0.0  0.0   2432   584 pts/0    S+   10:05   0:00 grep --color=auto service_worker.sh

Selective Termination with Pattern Matching

Now, let's selectively terminate only the processes with the --malfunctioning argument:

pkill -f "service_worker.sh --malfunctioning"

The -f option ensures that pkill matches against the full command line, including the arguments.

Verify that only the targeted processes have been terminated:

ps aux | grep service_worker.sh

You should now see only the "normal" and "emergency" processes:

labex     12360  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh normal
labex     12361  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh normal
labex     12364  0.0  0.0   2308   580 pts/0    S    10:05   0:00 /bin/bash /home/labex/project/service_worker.sh emergency
labex     12366  0.0  0.0   2432   584 pts/0    S+   10:06   0:00 grep --color=auto service_worker.sh

This demonstrates how you can selectively terminate processes based on specific patterns in their command lines.

Let's now terminate all remaining service worker processes:

pkill -f service_worker.sh

Verify that all service worker processes have been terminated:

ps aux | grep service_worker.sh

You should now only see the grep command itself:

labex     12367  0.0  0.0   2432   584 pts/0    S+   10:07   0:00 grep --color=auto service_worker.sh

Advanced Process Termination Options

In this step, we'll explore some advanced options of the pkill command that allow for more sophisticated process management.

Using Different Signal Types

By default, pkill sends the SIGTERM signal (signal 15) to processes. This signal allows processes to terminate gracefully, closing files and performing cleanup operations. However, there are cases where you might want to use a different signal.

Let's create a script that handles signals:

cd ~/project
nano signal_handler.sh

Add the following content to the script:

#!/bin/bash
trap 'echo "Received SIGHUP (1)"; exit 0' SIGHUP
trap 'echo "Received SIGINT (2)"; exit 0' SIGINT
trap 'echo "Received SIGTERM (15)"; exit 0' SIGTERM

echo "Process started with PID $$"
echo "Use: pkill -[signal] -f signal_handler.sh to send signals"
while true; do
  sleep 1
done

Make the script executable:

chmod +x ~/project/signal_handler.sh

Run the script in the background:

~/project/signal_handler.sh &

Now, let's try sending different signals to the process:

  1. Send a SIGHUP signal (signal 1):
pkill -HUP -f signal_handler.sh
  1. Start the script again and send SIGINT (signal 2):
~/project/signal_handler.sh &
pkill -INT -f signal_handler.sh
  1. Start the script again and send the default SIGTERM (signal 15):
~/project/signal_handler.sh &
pkill -f signal_handler.sh ## Default is SIGTERM

For each signal, you should see the corresponding message in the terminal output before the process exits.

Terminating Processes by Age

pkill allows you to target processes based on their age using the --newer and --older options.

Let's create a few processes with different start times:

cd ~/project
nano age_test.sh

Add the following content to the script:

#!/bin/bash
while true; do
  echo "Process running with PID $$"
  sleep 5
done

Make the script executable:

chmod +x ~/project/age_test.sh

Start the first process and record the reference file:

~/project/age_test.sh &
touch ~/project/reference_time

Wait a few seconds, then start two more processes:

sleep 5
~/project/age_test.sh &
~/project/age_test.sh &

Now, let's terminate only the processes that were started after the reference file was created:

pkill -f --newer ~/project/reference_time age_test.sh

Verify which processes are still running:

ps aux | grep age_test.sh

You should see only the first process is still running, as it was started before the reference file was created.

Terminate the remaining process:

pkill -f age_test.sh

Limiting pkill with Process Owner

You can also limit the actions of pkill to processes owned by a specific user. In a multi-user system, this is particularly useful.

For demonstration purposes, let's run a few processes as the current user:

~/project/rogue_app.sh &
~/project/rogue_app.sh &

Now, let's terminate these processes, but only those owned by your current user:

pkill -f -u $(whoami) rogue_app.sh

The -u option specifies the username of the process owner. The $(whoami) command substitution gets your current username.

Verify that all processes have been terminated:

ps aux | grep rogue_app.sh

You should only see the grep command itself in the output.

This ability to target processes by owner is particularly useful in multi-user environments where you want to avoid affecting processes belonging to other users.

Summary

In this lab, you have learned how to use the pkill command to manage processes in a Linux environment. This powerful command allows you to terminate processes based on various criteria, making it an essential tool for system administration.

Key concepts covered:

  1. Basic Process Termination: You learned how to identify running processes using the ps command and terminate them using pkill with basic pattern matching.

  2. Selective Process Termination: You explored how to use pattern matching to selectively target processes based on their command-line arguments, allowing for precise control over which processes to terminate.

  3. Advanced Process Termination Options: You discovered advanced options of pkill, including how to:

    • Send different signal types to processes
    • Terminate processes based on their age
    • Limit the scope of pkill to processes owned by a specific user

These skills are valuable for maintaining system stability, managing resources, and troubleshooting in Linux environments. By mastering the pkill command, you have added an important tool to your Linux system administration toolkit.