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
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.
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>
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}'
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"
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:
- 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
- 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
- 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
- Pausing and Resuming Process:
SIGSTOP (19)
can be sent to pause a process whileSIGCONT (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
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
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."
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.
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..."
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.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:
- Error Handling: Allows scripts to gracefully respond to errors and exceptions during execution.
- Resource Cleanup: Ensures proper cleanup of resources such as closing files or releasing locks before exiting.
- Termination Handling: Provides ways to handle script termination gracefully ensuring critical operations are completed or cleaned up.
- User Interruption: Enables script to respond to user interruptions such as pressing Ctrl+C or performing cleanup action or prompting for confirmation.
- Concurrency Control: Facilitates coordination and synchronization between concurrent processes or threads, preventing resource conflicts.
- Timeout Handling: Allows scripts to set timeouts for operations, preventing them from hanging indefinitely and consuming resources.
- 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:
- 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.
- 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
FUNDAMENTALS A Complete Guide for Beginners