Mar 25, 2012

Handling signals in bash

Due to the nature of a bash script, it is really difficult which can lead to a segmentation fault unless the script runs a binary within which can cause it afterwards. But what is the best way in bash in order to handle a segmentation fault? By catching its associated signal, that is, SIGSEGV (number 11, invalid memory reference).

In Linux, we have a great tool to do it: trap. The following script sets a handler up by means of the trap command. Its first parameter is the function or code which manages the exception, and the second one, the name (SEGV) or value (11) of the signal. We can also add more signals to the same trap.

[root@localhost ~]# cat segfault.sh
#!/bin/bash 

function trap_segfault 
{ 
    echo "We have a segmenation fault!"

    # Reset handler
    trap - 11
    exit 127 
} 

# Start handler
trap 'trap_segfault' 11
 
# Here code which can produce a segmentation fault, such as:
kill -SEGV $$ 1>&2

Apart from catching segmentation faults, we can use this technique so as to treat other signals inside a bash script. In order to take a look at all the signals provided by Linux, you might run 'trap -l' or 'kill -l'. But if you want to extend the information about them, you will have to resort to the own man.

[root@localhost ~]# man 7 signal
...
       Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
...

Next example handles SIGHUP to show the PID of the script and SIGINT to terminate it.

[root@localhost ~]# cat hup_int.sh 
#!/bin/bash 

function trap_sigint
{ 
    echo "Script terminated"

    # Reset handlers
    trap - HUP INT
    exit 0 
} 

# Start handlers
trap 'echo PID: $$\n' HUP
trap 'trap_sigint' INT 

while [ true ];
do
    sleep 1
done

[root@localhost ~]# ./hup_int.sh &
[1] 3046

[root@localhost ~]# kill -HUP 3046
[root@localhost ~]# PID: 3046

[root@localhost ~]# kill -INT 3046
[root@localhost ~]# Script terminated


And finally, also say that we can use this utility to leave out signals. For instance, the following order makes the script ignore SIGTERM.

trap : SIGTERM


No comments:

Post a Comment