Bash Process and Signal Handling

Process and signal handling in Bash refers to the management of running programs or processes and the handling of software interrupts sent to the Bash processes. In this guide, I’ll explore various aspects of managing processes, controlling their states, and handling different types of signals effectively. Let’s delve into it!

Processes in Bash

Understanding processes in Bash is crucial for efficient scripting and system resource management. Here’s an overview of processes in Bash:

What is Process?

A process is a task or executing instance of a program. Every command that is executed in a Bash shell starts a process. Each process is assigned a unique identification number called

Process ID (PID). Using the $$ variable you can view the PID of the current shell like the following:

echo "PID of current shell: $$"

Foreground and Background Processes

Foreground Process: Foreground processes are those that execute in the current shell and pause the execution of other commands until they finish. This process requires user interaction.

Background Process: Background processes are those that execute independently allowing the user to continue working in the foreground. To run a process in the background, use an ampersand & at the end of the command like the following:

long_process &

The & here allows the shell to continue executing commands without waiting for the background process to complete.

Different Process States

State indicates the current condition and activity of a process. In Bash, processes can be in various states, for example:

  1. Running State (R): Actively executes on the system.
  2. Sleeping State (S): Waits for an event to occur before continuing the execution.
  3. Interruptible Sleep State (S): Waits for an event to occur like the ‘sleeping state’ but can respond to signals.
  4. Uninterruptible Sleep State (D): Waits for a resource or hardware device that cannot be interrupted.
  5. Stopped State (T): Suspended by a signal and does not actively execute on the system.
  6. Zombie State (Z): Processes end but still have an entry in the process table.

Control Process States

Controlling process states refers to the way of scheduling and executing processes in a system. In Bash, processes can be controlled by using different commands like the following:

  1. “jobs” Command: Displays a list of current jobs (processes) with the job numbers running in the background. For example:

Executing the "jobs" command to list all the running jobs in the system

The job_spec (job number) is enclosed in ‘[ ]’ and the ‘+’ sign indicates the current job and the state of the process is specified as ‘Running’.

  1. bg” Command: When a process is suspended using CTRL + Z, it stops executing. The bg command then resumes the suspended background process. The basic syntax is:

bg [job_spec ...]

Controlling process states using "bg" command

  1. fg” Command: Resumes the execution of a stopped background process and moves it to the foreground. The basic syntax is:

fg [job_spec ...]

Basics of Signal Handling in Bash

Signal handling in Bash involves the management of signals like how they are received and processed in the system. Following is a detailed demonstration of signal handling in Bash:

What Are Signals?

Signals are software interrupts used to notify a process about specific events or actions such as interruption or termination. Generally, signals are sent by the kernel, users, or other processes. Every signal within a system serves an individual purpose and can be handled by different processes whenever needed.

Some Common Signals

There are several standard signals, each serving a specific purpose. Some common signals are:

  1. SIGINT (Interrupt): Interrupts and terminates a process (using CTRL + C).
  2. SIGTERM (Terminate): Requests for a process termination.
  3. SIGKILL (Kill): Forces a process for immediate termination.
  4. SIGSTOP (Stop): Suspends process execution.
  5. SIGCONT (Continue): Resumes the execution of a paused process.

Signal Sending

To send a signal to a process in the system, use the kill command. The basic syntax to send a signal to a process:

kill -SIGNAL PID

To view the PID of a running process, run the ps aux | grep PROCESS_NAME syntax in the terminal.

Here’s how to send different signals to control process states:

  1. Pause Process:

kill -STOP PID #SIGSTOP signal pauses the execution of a process

Pausing a process using SIGSTOP signal

  1. Resume Process:

kill -CONT PID #SIGCONT signal resumes the execution of a paused process

Continues a process using SIGCONT signal

  1. Terminate Process:

kill -TERM PID #SIGTERM signal terminates a process gracefully

Terminating a process using SIGTERM signal

Or,

kill -KILL PID #SIGKILL signal terminates a process forcefully

Terminating a process using SIGKILL signal

You can also specify the signals using the ‘SIG’ prefix. For example, kill -SIGSTOP PID.

Signal Propagation

In Bash, signal propagation is done mostly from parent processes to their child processes. When a new or child process is created, it inherits the same signal settings i.e. it follows the same signal handling mechanism as its parent process. To control signal propagation among processes, Bash provides mechanisms such as the trap command to set up signal handlers (Block of codes executed in response to specific signals) and the kill command to send signals.

Trapping and Handling Signals in Bash Scripts

In Bash scripting, the trap command is used to specify the execution of Bash commands when a signal is received. The basic syntax is as follows:

trap COMMAND SIGNAL

Here, COMMAND specifies the action to be taken and SIGNAL specifies lists of signals to trap.

Here’s a practical example demonstrating how you can trap and handle the signals SIGINT and SIGTERM in Bash scripts:

#!/bin/bash

#Trapping SIGINT signal
trap "echo SIGINT terminated the process; exit" SIGINT

#Trapping SIGTERM signal
trap "echo SIGTERM terminated the process; exit" SIGTERM

#Printing the process ID
echo $$

#setting counter for the loop
counter=0

#An infinite loop
while true
do
echo "Loop " $((++counter))
sleep 3
done

EXPLANATION

The script sets up traps for SIGINT and SIGTERM signals. The $$ holds the PID of the script. The while loop here increases the value of the counter variable (initially which was set to zero), prints it to the terminal, and sleeps for 3 seconds before each iteration. As the script uses an infinite while loop, it exits with a termination message only when the SIGINT or SIGTERM signals are received.

Output for SIGINT:Trapping SIGINT signal in Bash

As you can see from the image after pressing CTRL + C, the script reacts to the signal SIGINT, and the output message inside the signal is printed to the terminal.

Output for SIGTERM:Trapping SIGTERM signal in Bash

From the above image, you can see that after running the kill command with the PID (93042) of my script from a new terminal, the script finally reacts to the SIGTERM signal and prints the output message inside it.

Conclusion

So far, you have learned several aspects of the Bash process and signal handling. Practice these more and more to become a proficient Bash scripter!

People Also Ask

What is a daemon script in Bash?

Daemon script or daemon is a type of background process that runs continuously on a system without any user interaction. Daemons are generally used in Unix-like operating systems.

Can Bash scripts handle multiple signals simultaneously?

Yes, Bash scripts handle multiple signals simultaneously by setting different trap commands for each signal. For example:

trap "echo SIGINT terminated the process; exit" SIGINT
trap "echo SIGTERM terminated the process; exit" SIGTERM

What are zombie processes, and how can Bash scripts prevent them?

Zombie processes are the child processes that have terminated but their parent process has not retrieved their exit status yet. Bash scripts can prevent them when the parent process waits for and cleans up the terminated child processes This can be accomplished by trapping the SIGCHLD signal and calling the wait command to collect the exit status.

How can I terminate a process forcefully in Bash?

To terminate a process forcefully in Bash, use the kill command with the SIGKILL signal. For example:

kill -SIGKILL PID

Related Articles


<< Go Back to Bash Scripting Tutorial

Rate this post
LINUX
FUNDAMENTALS
A Complete Guide for Beginners Enroll Course Now
Nadiba Rahman

Hello, This is Nadiba Rahman, currently working as a Linux Content Developer Executive at SOFTEKO. I have completed my graduation with a bachelor’s degree in Electronics & Telecommunication Engineering from Rajshahi University of Engineering & Technology (RUET).I am quite passionate about crafting. I really adore exploring and learning new things which always helps me to think transparently. And this curiosity led me to pursue knowledge about Linux. My goal is to portray Linux-based practical problems and share them with you. Read Full Bio

Leave a Comment