Bash Signals Handling

LINUX
FUNDAMENTALS
A Complete Guide for Beginners Enroll Course Now

In the realm of bash scripting, signals stand as a cornerstone for ensuring script stability and responsiveness. Signals act as a silent messenger of the Linux environment. It carries important information about process events and system interactions. Thus signal handling is a fundamental skill for any bash script developer. This article will introduce bash signals handling and dive into different aspects of signals and signals handling in bash scripting.

What is Signal in Linux?

In Linux, a signal is a notification sent to a process to indicate an event. Typically it is triggered by the operating system, hardware, or other processes. Signals serve as a form of inter-process communication. It allows the processes to communicate with each other and with the operating system kernel. Signals can signify various events, including process termination, user interrupts, errors, and system events. A unique identifier represents each signal and has predefined behaviors associated with it. Signals play a crucial role in managing the execution and behavior of processes in the Linux operating system.

List of Signals

Each of the signals has a unique number. Signal numbers are important because these numbers can be used to identify each signal in the signal. To get a list of all signals and their corresponding numbers in a Bash terminal execute the following command in the Bash terminal:

kill -l
EXPLANATION

After executing the command, the terminal will display a list of all signals along with their corresponding numbers. Each signal is represented by its name and its number.

list of all signals in bash

The terminal displays the list of all available signals.

Common Signals With Definition

In Linux, there are several predefined signals. Each signal is identified by a unique name and a corresponding number. Here is a list of some common predefined signals along with their corresponding numbers and their definitions:

  • SIGHUP (Hangup) (1): Typically sent to indicate the termination of the controlling process. It often prompts daemons to reinitialize or restart.
  • SIGINT (Interrupt) (2): Sent by pressing Ctrl+C. Usually terminates a process.
  • SIGQUIT (Quit) (3): Similar to SIGINT but produces a core dump upon termination.
  • SIGILL (Illegal Instruction) (4): Indicates an attempt to execute an illegal or undefined instruction.
  • SIGABRT (Abort) (6): Sent by the abort(3) function, indicating abnormal termination requested by the process itself.
  • SIGFPE (Floating-Point Exception) (8): Indicates an arithmetic error such as dividing by zero or floating-point overflow.
  • SIGKILL (Kill) (9): Unconditionally terminates a process. Cannot be caught or ignored.
  • SIGSEGV (Segmentation Fault) (11): Indicates an invalid memory reference or segmentation violation.
  • SIGPIPE (Broken Pipe) (13): Sent to a process attempting to write to a pipe without a process reading from it.
  • SIGALRM (Alarm Clock) (14): Sent by the alarm(2) system call or set timer (2) timer expiration.
  • SIGTERM (Termination) (15): A termination request sent to a process typically causing it to exit successfully.
  • SIGCHLD (Child Status Changed) (17): Sent to the parent process when a child process terminates or stops.
  • SIGCONT (Continue) (18): Sent to instruct a stopped process to continue executing.
  • SIGSTOP (Stop) (19): Stops a process for debugging or other administrative purposes. Cannot be caught or ignored.
  • SIGTSTP (Terminal Stop) (20): Sent by pressing Ctrl+Z to temporarily stop a process running in the foreground.
  • SIGTTIN (Background Read) (21): Sent to a background process attempting to read from its controlling terminal.
  • SIGTTOU (Background Write) (22): Sent to a background process attempting to write to its controlling terminal.
  • SIGUSR1 (User Signal 1) (10): A signal that can be used for user-defined purposes.
  • SIGUSR2 (User Signal 2) (12): Another signal available for user-defined purposes.

How to Handle Bash Signals?

Handling Bash signals involves setting up traps to intercept signals sent to a script or a running process. This is achieved using the trap command, followed by the action to be taken when a specific signal is received. By defining trap handlers, scripts can gracefully respond to signals, ensuring proper cleanup, error handling, or other necessary actions based on the signal received.

A. Sending Signals

Sending signals in Bash scripting involves initiating communication between processes or scripts by transmitting signals to them. In Bash scripting, you can send signals to processes using the kill command. This command allows you to send signals to a specific process or group of processes identified by their process ID (PID) or process group ID (PGID). The basic syntax for sending a signal with the kill command is:

kill <signal_number> <process_id>
EXPLANATION

Here,

  • kill: Command to send signals to the processes.
  • signal_number: Specifies the signal to send to the process. It can be either the signal’s numeric value or its name.
  • process_id: Represents the process ID of the target process.

For example, to forcefully terminate a process with process ID 5678 with SIGKILL signal execute the following command:

kill -9 5678

Note: To get the process ID (PID) use the “ps aux” command or the “pgrep” utility.

For example:

ps aux | grep "process_name" | awk '{print $2}'

find PID of a process using ps command

The ps command which stands for “process status” displays information about running processes. The aux option shows processes from all users with the user information and without a controlling terminal. Then it pipes the output to filter all lines containing process_name using the grep command. Finally, the awk command extracts the second column which is the PID from the filtered lines. Here PID of the main process and the child processes spawned from the main process are displayed. Usually, the 1st PID is the PID of the main process.

pgrep "process_name"

find PID of a process using pgrep utility

The pgrep is a command line utility used to search for processes based on various criteria, such as process name, the user owning the process, or other attributes. Without any option, it just returns the PID of the first matching process. This command will search for a process named process_name and return its PID if the process is found. Here, the PID of the first matching Firefox process is shown.

B. Applications of Sending Signals

Sending signals in bash scripting is a fundamental aspect of process management and communication. Here are some common applications for sending signals:

  1. Terminating Processes: The user can send signals like SIGTERM (15) to gracefully terminate a process. For example, to stop a running application, the user can send a SIGTERM signal to its process ID (PID) like the following:
    kill -15 PID
  2. Forcefully Killing Processes: In situations where a process does not respond to a regular termination signal, the user can send a SIGKILL (9) signal to force it to stop immediately. To do so:
    kill -9 PID
  3. Reloading Configuration: Some applications reload their configuration when they receive a SIGHUP (1) signal. This can be useful for updating settings without restarting the entire application.
    kill -1 PID
  4. Pausing and Resuming Process: SIGSTOP (19) can be sent to pause a process while SIGCONT (18) can be sent to resume a paused process. So, the command will look like:
    kill -19 PID
    kill -18 PID

C. Trapping Signal

In Bash, the trap command is used to catch and handle signals sent to the shell or shell scripts. It allows you to define actions or commands to execute when a particular signal is received. The basic syntax of the trap command is:

trap 'commands' SIGNALS
EXPLANATION

Here, the ‘commands’ represent the action to be taken when the specified signal is received. Signals can be specified by their names or corresponding numbers.

Trapping signals in Bash involves using the trap command to specify actions to execute when a particular signal is received. This allows the user to define custom behavior for your script when it encounters different signals. Trapping signal is useful for gracefully handling interruptions and ensuring proper cleanup or response in your Bash scripts.

For example, to trap the SIGINT signal (sent when the user presses Ctrl+C), you can use:

trap 'echo "Ctrl+C pressed. Exiting..."; exit' SIGINT

This command will display a message and exit the script gracefully when Ctrl+C is pressed.

You can trap multiple signals by separating them with spaces:

trap 'echo "Signal received."' SIGINT SIGTERM

This will execute the specified command whenever either SIGINT or SIGTERM is received.

D. Ignoring Signals

Ignoring signals in Bash involves using the trap command to override the default behavior of signals and make them not affect the script. This is particularly useful when the user wants to prevent certain signals from interrupting the execution of the script. Here is how to ignore signals in bash scripting:

trap '' SIGNAL_NAME
EXPLANATION

Here, '' represents an empty action, indicating that no action should be taken when the specified signal (SIGNAL_NAME) is received.

For example, to ignore the SIGINT signal (sent when the user presses Ctrl+C), you can use:

trap '' SIGINT

This command will cause the script to continue executing normally even if Ctrl+C is pressed.

E. Bash Trap Exit

In Bash scripting, the trap command is a shell built-in command to catch and handle signals in the shell session. The trap Exit is specifically a command that allows the user to define actions to be executed when the script or shell session exits whether it happens normally or due to an error. Using trap Exit, the user can ensure that certain tasks or actions can be performed before the script terminates regardless of the exit status. While handling long tasks using bash scripting is very common to create some temporary files or child processes that are not needed after the main task is complete. The trap EXIT command can be used to effectively handle those files or processes.  The following script showcases how to use the trap EXIT command to handle the cleanup task before the script exits:

#!/bin/bash

# Function to clean up temporary files
cleanup() {
  echo "Cleaning up temporary files..."
  rm -f temp_file1 temp_file2
}

# Trap EXIT to execute the cleanup function before the script exits
trap cleanup EXIT

# Main script logic
echo "Creating temporary files..."
touch temp_file1 temp_file2
echo "Main script execution completed."
EXPLANATION

This bash script first defines a cleanup() function responsible for removing temporary files. Then the trap command is used to intercept the EXIT signal and execute the cleanup() function accordingly. Then the main script creates two temporary files. Upon completion of the script, the cleanup() function is invoked and the cleanup of the temporary file happens.

clear temporary file before script exit

Here, temporary files are removed after script execution.

F. Bash Wait for Keypress

Signal handling in bash typically involves capturing and responding to signals sent to a script or process. While waiting for a keypress doesn’t directly involve signals, signal handling can be integrated into scripts that wait for input to respond to external events like interrupts or termination signals. In bash scripting waiting for a keypress can be achieved using the read command with the -n option to read a specific number of characters. Here is an example of how to do that:

#!/bin/bash

# Function to generate the isosceles triangle pattern
generate_triangle() {
  rows=$1
  for ((i=1; i<=rows; i++)); do
    for ((j=1; j<=rows-i; j++)); do
       echo -n " "
    done
    for ((k=1; k<=2*i-1; k++)); do
       echo -n "*"
    done
    echo ""
  done
}

# Function to handle SIGINT (Ctrl+C)
sigint_handler() {
  echo "SIGINT received. Exiting."
  exit 1
}

# Function to prompt user to continue or exit
prompt_continue() {
  read -n 1 -s -p $'Do you want to continue? Press Enter to continue, or any other key to exit.\n' key
  echo ""
  if [ -z "$key" ]; then
    return 0
  else
    return 1
  fi
}

# Trap SIGINT to call sigint_handler function
trap sigint_handler SIGINT

# Main script logic
while true; do
  # Prompt user for the number of rows
  read -p "Enter the number of rows for the isosceles triangle: " rows

  # Generate the triangle pattern
  generate_triangle $rows

  # Prompt user to continue or exit
  prompt_continue || break
done

echo "Exiting..."
EXPLANATION
This bash script generates an isosceles triangle pattern based on the user’s input for the number of rows. Then the script incorporates signal handling for SIGINT (Ctrl+C) using the trap command to gracefully exit the script when interrupted. After generating the triangle the script prompts the user to either continue or exit. If the user chooses to continue by pressing Enter, the script repeats. Otherwise, it exits with a confirmation message.

bash script waiting for key press from keyboard

Here, first, the script’s execution ended naturally as non Enter key was pressed. Then script execution ended due to the SIGINT signal. During the execution of the bash script, it waits for keypress for further continuation.

Why Signal Handling is Needed in Bash Scripting?

Signal handling in bash scripting is important for the script’s stability and reliability. It is also crucial for creating a proper user experience. Here are some of the practical usages of signal handling:

  1. Error Handling: Allows scripts to gracefully respond to errors and exceptions during execution.
  2. Resource Cleanup: Ensures proper cleanup of resources such as closing files or releasing locks before exiting.
  3. Termination Handling: Provides ways to handle script termination gracefully ensuring critical operations are completed or cleaned up.
  4. User Interruption: Enables script to respond to user interruptions such as pressing Ctrl+C or performing cleanup action or prompting for confirmation.
  5. Concurrency Control: Facilitates coordination and synchronization between concurrent processes or threads, preventing resource conflicts.
  6. Timeout Handling: Allows scripts to set timeouts for operations, preventing them from hanging indefinitely and consuming resources.
  7. Custom Actions: Provides the flexibility to define custom actions or behaviors in response to specific signals or events

Practice Tasks on Bash Signals Handling

If you aim to be better at handling bash signals, then you can try creating a Bash script for the following problems using the concept of bash signal handling which is discussed in this article:

  1. Write a bash script that traps the SIGINT signal and executes a cleanup function when Ctrl+C is pressed. The cleanup function should remove any temporary files created by the script.
  2. Develop a script that allows the user to pause, resume, or terminate a specific process by sending the appropriate signals. The script should prompt the user for the action and the process ID.

Conclusion

In summary, bash signals handling is a critical aspect of script development. It enables users to proactively respond to various events and interruptions. I hope the information outlined in this article helps you be well-prepared to navigate the intricacies of signal handling and create efficient bash scripts.

People Also Ask

How does Bash handle signals?

Bash handles signals by intercepting them with the trap command, allowing scripts to respond to specific signals. When it receives a signal, bash executes the specified command or function associated with that signal. This enables scripts to gracefully handle interruptions, errors, and other events ensuring smooth execution.

What is signal handling in Linux?

Signal handling in Linux involves managing and responding to signals which are notifications sent to processes to indicate events such as process termination, user interrupts, errors, and system events. These signals enable processes to communicate with each other and with the operating system kernel. By intercepting signals using the trap command user can define actions to be taken when specific signals are received. It plays an important role in ensuring system stability.

What is SIGINT in shell script?

SIGINT in shell scripting stands for “signal interrupt”. It is triggered by pressing the Ctrl+C key from the keyboard and is commonly used to interrupt or terminate a running process. When a shell script receives a SIGINT signal, it typically terminates the script execution and returns control to the user. This signal allows the user to gracefully stop executing scripts or commands that are running in the shell environment.

What is exec in Bash?

In bash, the exec command is a built-in shell command. It is used to replace the current shell processes with a new program. When the exec command is executed it loads and runs the specified program in place of the current shell. That means that the current shell process is replaced entirely by the new program and any subsequent commands in the script are not executed. The exec command is often used to efficiently run commands scripts or applications. It is particularly useful for optimizing resource usage in shell scripts.

What is the signal handler function?

A signal handler function in bash is a designated subroutine responsible for executing specific actions when a signal is received by a script or process. When a signal is triggered the operating system invokes the corresponding signal handler function to handle the signal appropriately. These functions are defined within the script or program and are registered using the trap command. It specifies the desired action or commands to be executed upon signal reception.

Can the signal handler be interrupted?

Yes, the signal handler can be interrupted if another signal of higher priority is received while the handler is executing. In such cases the signal currently being handled will be temporarily suspended and the new signal will be processed instead. This interruption can occur if multiple signals are sent to a process concurrently or in quick succession. It is essential to design the signal handling mechanisms to account for potential interruptions and ensure that critical actions are appropriately managed.

Related Articles


<< Go Back to Bash Process and Signal Handling | Bash Scripting Tutorial

Rate this post
Ridoy Chandra Shil

Hello everyone. I am Ridoy Chandra Shil, currently working as a Linux Content Developer Executive at SOFTEKO. I am a Biomedical Engineering graduate from Bangladesh University of Engineering and Technology. I am a science and tech enthusiast. In my free time, I read articles about new tech and watch documentaries on science-related topics. I am also a big fan of “The Big Bang Theory”. Read Full Bio

Leave a Comment