Using -exec with kill command

I am trying to execute the following command in which I use the kill and exec commands.

kill -l -exec grep -i 'term' {} +

Since, kill -l returns a list of all kill signals, I want to find all those signals which contain the word ‘term’ using grep with case insensitive -i flag. But, it returns the following errors. Could someone advise why could this be?

-bash: kill: grep: invalid signal specification
-bash: kill: -i: invalid signal specification
15
-bash: kill: {}: invalid signal specification
-bash: kill: +: invalid signal specification
Asked By: MathMan

||

With the -l option, the output of bash‘s kill builtin when not in POSIX mode is:

$ kill -l
 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     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGINFO     30) SIGUSR1     31) SIGUSR2     

I can group each pair number) signal with xargs -n 2

So this should do what you asked for:

kill -l | xargs -n 2 | grep -i term
Answered By: lauhub

-exec cmd {} + is an idiom of the find command and the find command alone. It’s used there to run cmd with the files it has found as arguments. -exec there is not an option, it’s generally called a predicate and is used in the chain of conditions and actions that make up a find expression (find also supports options which are passed before the list of files / directories it should start finding from).

kill is a command that is builtin in most shells and used to send signals to processes based on their process ID or the shell job they’re member of.

Most implementations also support a -l option which lists the signals that may be sent in a format that varies with the implementation. Some list signals one per line, some in column, some just space separated, some include both the the signal name and number.

If, in addition to the -l option, you pass a signal name or number (with or without the SIG prefix with some implementation), some kill implementations will output the corresponding signal number / name, though some always print the name, and some only accept numbers.

So:

kill -l TERM

for instance, with some kill implementations including the kill builtin of the zsh shell will output:

15

Where 15 on most if not all systems is the actual value of SIGTERM.

In the zsh shell, the signal names (+ EXIT which is also used in trap) are also available in the $signals special array:

$ echo $signals
EXIT HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS ZERR DEBUG

The signal number for a given signal is its index in the array minus 1.

$ echo $signals[15+1]
TERM
$ echo $(( signals[(I)TERM] - 1 ))
15

Or for a case insensitive matching:

$ set -o extendedglob
$ echo $(( signals[(I)(#i)term] - 1 ))
15

(kill -l term also works in many kill implementations).

Answered By: Stéphane Chazelas
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.