Bash Trap Signals | Capture CTRL+C [Practical Examples]


Shell Scripting

Author: Omer Cakmak
Reviewer: Deepak Prasad

Why do we need to trap signals when executing code?

While your program is running, if you press Ctrl-C or Ctrl-\, your program terminates as soon as the signal arrives. There are times when you would rather not have the program terminate immediately after the signal arrives. You could arrange to ignore the signal and keep running or perform some sort of cleanup operation before actually exiting the script. The trap command allows you to control the way a program behaves when it receives a signal.

 

Understanding signals

  • A signal is defined as an asynchronous message that consists of a number that can be sent from one process to another, or by the operating system to a process if certain keys are pressed or if something exceptional happens.
  • The trap command tells the shell to terminate the command currently in execution upon the receipt of a signal. If the trap command is followed by commands within quotes, the command string will be executed upon receipt of a specified signal.
  • The shell reads the command string twice, once when the trap is set, and again when the signal arrives.
  • If the command string is surrounded by double quotes, all variable and command substitution will be performed when the trap is set the first time.
  • If single quotes enclose the command string, variable and command substitution do not take place until the signal is detected and the trap is executed.

Bash scripts are an integral part of Linux systems. Many manual processes can be automated with bash scripts. You can ensure that the actions to be taken proceed in a way that does not require the intervention of the user. However, users may prevent the script from working properly. For example; They can stop the script from running with the CTRL+C combination. There is no way to prevent this, but you can catch such key combinations in your bash script.

To show all signals and codes, execute the following command on the console;

foc@pardus:/$ trap -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

Now let's look at "How to Capture CTRL+C in Bash"

 

How to use trap in shell scripts (syntax)

The trap command is used when writing bash scripts on Linux. The standard usage of the trap command is as follows.

trap 'command; command' signal-number
trap 'command; command' signal-name

For Example

trap 'rm tmp*; exit 1' 0 1 2 15
trap 'rm tmp*; exit 1' EXIT HUP INT TERM

When any of the signals 1 (hangup), 2 (interrupt), or 15 (software termination) arrives, remove all the tmp files and exit.

 

Resetting trap signals

To reset a signal to its default behavior, the trap command is followed by the signal name or number. Traps set in functions are recognized by the shell that invoked the function, once the function has been called. Any traps set outside the function are also recognized with the function.

  • trap INT: Resets the default action for signal 2, SIGINT. The default action is to kill the process when the interrupt key (Ctrl-C) is pressed.
  • trap 2: Resets the default action for signal 2, SIGINT, which is used to kill a process (i.e., Ctrl-C).
  • trap 'trap 2' 2: Sets the default action for signal 2 (SIGINT) to execute the command string within quotes when the signal arrives. The user must press Ctrl-C twice to terminate the program. The first trap catches the signal, and the second trap resets the trap back to its default action, which is to kill the process.

 

Ignoring trap signals

If the trap command is followed by a pair of empty quotes, the signals listed will be ignored by the process. Here, Signals 1 (SIGHUP) and 2 (SIGINT) will be ignored by the shell process.

trap " " 1 2 
or
trap "" HUP INT

 

Trap Command Usage Examples

An interrupt signal ( 2 - SIGINT ) is sent to the system when the user uses the CTRL + C key combination. After this signal, the console drops to a blank line unless otherwise stated.

 

Example-1: Without trapping any signal

Below is the script that expects the user to enter a value;

#!/bin/bash
echo "Enter a value"
read input
echo Entered value: $input

Run this script as follows;

foc@pardus:~$ ./trap_epl.sh 
Enter a value

After this command the cursor blinks and waits for a value from the user. If the process is stopped with the CTRL+C key combination instead of entering a value, the terminal switches to a new line.

foc@pardus:~$ ./trap_epl.sh 
Enter a value
^C
foc@pardus:~$ 

Now let's capture the CTRL+C key combination with the trap command. Let's update the script as follows.

 

Example-2: Capture trap signal (Ctrl+C, Ctrl+Z, Ctrl+\)

In this example, we have setup trap signal to capture different signals. So our shell script will continue to run in while loop and will terminate for known singals. Instead it will capture and ignore them. The script will only terminate if we enter "stop":

#!/bin/bash
trap 'echo -e  "\nCtrl-C will not terminate $0."'  INT
trap 'echo -e  "\nCtrl-\\ will not terminate $0."'  QUIT
trap 'echo  -e "\nCtrl-Z will not terminate $0."'  TSTP
echo "Enter any string after the prompt. When you are ready to exit, type \"stop\"."
while true
do
   read -p "Go ahead...> " INPUT
   if [[ $INPUT == [Ss]top ]]
   then
       break
   fi
done

Let's execute the script:

~]# sh /tmp/trap_eg.sh 
Enter any string after the prompt. When you are ready to exit, type "stop".
Go ahead...> ^C
Ctrl-C will not terminate /tmp/trap_eg.sh.
^Z
Ctrl-Z will not terminate /tmp/trap_eg.sh.
^\
Ctrl-\ will not terminate /tmp/trap_eg.sh.
stop

 

Execute bash functions with traps

If you use a trap to handle a signal in a function, it will affect the entire script, once the function is called. The trap is global to the script.

The syntax remains the same as we showed earlier, just replace the command section with the handler function to be used.

The syntax is as follows:

trap 'signal_handler_function_name' SIGNAL LIST

So assuming we want to perform some cleanup when the script receives Ctrl+C then all the code can be placed in a function and that function can be executed for respective trap signals:

#/bin/bash 

function handler() 
{
  echo Hey, received signal : SIGINT 
  echo "I will do some task here and exit"
  exit 1
}

# $$ is a special variable that returns process ID of current  
# process/script 
echo My process ID is $$ 

# handler is the name of the signal handler function for SIGINT signal 
trap 'handler' SIGINT

while true; 
do
  sleep 1
done

Here is a sample shell script which will capture the current process PID and trap ctrl+c events. If this trap is received, then handler function will be executed.

Output:

~]# sh /tmp/trap_eg.sh 
My process ID is 6067
^CHey, received signal : SIGINT
I will do some task here and exit

 

Summary

As a result bash scripts are an integral part of Linux systems. The user's use of the CTRL+C combination is an inevitable result. Of course, precautions should be taken for this result.

Let's see what can be done when the CTRL + C combination comes.

  • Cache can be cleared in operations such as package installation.
  • Using this function it is possible to return to the pre-interruption period. Old configurations can be copied.
  • Warnings can be added to the function. After the script is stopped, the steps that the user should take can be written on the screen.

For such reasons, you should add this function to your bash script.

 

Further Reading

BASH - using trap ctrl+c

 

Omer Cakmak

Omer Cakmak

He is highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

1 thought on “Bash Trap Signals | Capture CTRL+C [Practical Examples]”

Leave a Comment