Search code examples
linuxshellsedsignalsaix

Find signal number by signal name


I want to trap signal SIGTSTP, as simple as this:

trap "" SIGTSTP

However, pure shell (sh) does not support signal name, so a trap must use the signal number instead, like this:

trap "" 20

Problem: signal numbers are OS-dependent, so SIGTSTP in Linux is 20 but in AIX it's 18.

So to make it generic I decide to extract signal number from the result of trap -l. The raw input is:

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGEMT       8) SIGFPE
 9) SIGKILL     10) SIGBUS      11) SIGSEGV     12) SIGSYS
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGURG
17) SIGSTOP     18) SIGTSTP     19) SIGCONT     20) SIGCHLD
21) SIGTTIN     22) SIGTTOU     23) SIGIO       24) SIGXCPU
25) SIGXFSZ     27) SIGMSG      28) SIGWINCH    29) SIGPWR
30) SIGUSR1     31) SIGUSR2     32) SIGPROF     33) SIGDANGER
34) SIGVTALRM   35) SIGMIGRATE  36) SIGPRE      37) SIGVIRT
38) SIGALRM1    39) SIGWAITING  50) SIGRTMIN    51) SIGRTMIN+1
52) SIGRTMIN+2  53) SIGRTMIN+3  54) SIGRTMAX-3  55) SIGRTMAX-2
56) SIGRTMAX-1  57) SIGRTMAX    60) SIGKAP      61) SIGRETRACT
62) SIGSOUND    63) SIGSAK   

I can't use grep, because the feature that I need, --only-matching, is not always supported. trap -l | grep -oE "[0-9]+\) SIGTSTP" | cut -d')' -f1 works well, but only in Linux.

I also failed to use sed because of the greedy problem described here

So trap -l | sed -nr 's/.*([0-9]+)\) SIGTSTP.*/\1/p' only returns 8, not 18

I want to make the extraction as generic as possible, so I won't assume SIGTSTP is a double-digit code, even when in reality it is.

Any suggestion?


Solution

  • Try constraining the match with a word boundary:

    trap -l | sed -nr 's/.*\b([0-9]+)\) SIGTSTP.*/\1/p'

    This tested correctly [for me] for the target string as well as SIGPIPE.