Linux 在 Bash 中识别接收到的信号名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9256644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:32:39  来源:igfitidea点击:

Identifying received signal name in Bash

linuxbashshell

提问by Lunar Mushrooms

When a signal is received, I can execute some commands using trap. Example:

当接收到信号时,我可以使用trap. 例子:

trap 'echo hello world' 1 2

If any of the signals specified is received, the hello world' is displayed.

如果接收到任何指定的信号,则会显示 hello world'。

But how can I print/identify the received signal name?

但是如何打印/识别接收到的信号名称?

采纳答案by perelman

(If you only have the number of a signal and want the name, kill -l $SIGNAL_NUMprints the name of a signal; you can avoid that by using the signal names instead of numbers in your call to trapas below.)

(如果您只有信号的编号并且想要名称,则kill -l $SIGNAL_NUM打印信号的名称;您可以通过在调用中使用信号名称而不是数字来避免这种情况,trap如下所示。)

This answersays that the only way to identify which signal you trapped in bash is to write a separate wrapper for each different signal you want to trap. Another answer on that same questionprovides a wrapper function to do it for you:

这个答案说,识别您在 bash 中捕获的信号的唯一方法是为您想要捕获的每个不同信号编写一个单独的包装器。同一问题的另一个答案提供了一个包装函数来为您完成:

Code:

代码:

#!/bin/bash

trap_with_arg() {
    func="" ; shift
    for sig ; do
        trap "$func $sig" "$sig"
    done
}

func_trap() {
    echo "Trapped: "
}

trap_with_arg func_trap INT TERM EXIT

echo "Send signals to PID $$ and type [enter] when done."
read # Wait so the script doesn't exit.

If I run that, then I can send signals to the process and I get output like

如果我运行它,那么我可以向进程发送信号并得到类似的输出

Trapped: INT
Trapped: TERM
Trapped: EXIT

回答by Phil

Within the trap (when triggered via a signal), the $? variable is initially set to the signal number plus 128, so you can assign the signal number to a variable by making the first statement of the trap action to something like

在陷阱内(当通过信号触发时), $? 变量最初设置为信号编号加 128,因此您可以通过将陷阱操作的第一个语句设置为类似的内容来将信号编号分配给变量

sig=$(($? - 128))

You can then get the name of the signal using the kill command

然后,您可以使用 kill 命令获取信号的名称

kill -l $sig

回答by Yoav Kleinberger

a simple way to do this:

一个简单的方法来做到这一点:

_handler() {
   signal=
   echo signal was $signal
 }

 trap '_handler SIGTERM' SIGTERM
 trap '_handler SIGINT'  SIGINT

回答by Steven

Referring to the $?solution above: $?will reflect the exit code of the last executed command. Consider this:

参考$?上面的解决方案:$?会反映上次执行命令的退出码。考虑一下:

#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600

If you run this and hit Ctrl-C, it will print CODE: 130. That's because the sleepexecutable was interrupted by the SIGINT and exited with that code.

如果您运行它并按Ctrl-C,它将打印CODE: 130。那是因为sleep可执行文件被 SIGINT 中断并以该代码退出。

Compare that to:

比较一下:

#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X

If you run this and hit Ctrl-C, it will print CODE: 0, presumably because the readcommand is a builtin and exit code rules are different (same happens if you would interrupt while : ; do : ; done).

如果您运行它并按Ctrl-C,它将打印CODE: 0,大概是因为该read命令是内置命令并且退出代码规则不同(如果您中断,也会发生同样的情况while : ; do : ; done)。

So, $?only tells you about the signal if it interrupted an external command, andif that particular program has not caught the signal and exited with its own exit code. Point in case is the bash script above: upon receiving a SIGINT, it will exit with code 1, not 130.

因此,$?只有在它中断了外部命令时才告诉您信号,以及该特定程序是否未捕获该信号并使用其自己的退出代码退出。以防万一是上面的 bash 脚本:在收到 SIGINT 后,它将以代码退出1,而不是130.

回答by Brian White

for s in {1..64} ;do trap "echo trap $s" $s ;done

Or without bash-isms

或者没有 bash-isms

s=1 ;while [ $s -le 64 ] ;do trap "echo trap $s" $s ;s=$((s+1)) ;done

Sets 64 individual traps, one for each possible signal.

设置 64 个单独的陷阱,每个可能的信号一个。