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:
- Running State (R): Actively executes on the system.
- Sleeping State (S): Waits for an event to occur before continuing the execution.
- Interruptible Sleep State (S): Waits for an event to occur like the ‘sleeping state’ but can respond to signals.
- Uninterruptible Sleep State (D): Waits for a resource or hardware device that cannot be interrupted.
- Stopped State (T): Suspended by a signal and does not actively execute on the system.
- 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:
-
“jobs” Command: Displays a list of current jobs (processes) with the job numbers running in the background. For example:
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’.
-
“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 ...]
-
“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:
- SIGINT (Interrupt): Interrupts and terminates a process (using CTRL + C).
- SIGTERM (Terminate): Requests for a process termination.
- SIGKILL (Kill): Forces a process for immediate termination.
- SIGSTOP (Stop): Suspends process execution.
- 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:
-
Pause Process:
kill -STOP PID #SIGSTOP signal pauses the execution of a process
-
Resume Process:
kill -CONT PID #SIGCONT signal resumes the execution of a paused process
-
Terminate Process:
kill -TERM PID #SIGTERM signal terminates a process gracefully
Or,
kill -KILL PID #SIGKILL signal terminates a process forcefully
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
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:
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:
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
- How to List and Start Multiple Bash Processes? [Easy Ways]
- Check If a Process is Running in Bash [6 Methods]
- Process Management in Bash
- Exit Codes in Bash
- Bash Signals Handling
<< Go Back to Bash Scripting Tutorial
FUNDAMENTALS A Complete Guide for Beginners