bash
在 Kubuntu Trusty 64 位上运行4.3。请看以下两个文件:
陷阱int.sh
#! /bin/bash
trap "echo Exiting" INT
cat </dev/urandom >/dev/null
echo Hello
捕获退出.sh
#! /bin/bash
trap "echo Exiting" EXIT
cat </dev/urandom >/dev/null
echo Hello
现在,在点击 ^C 时,捕获 SIGINT 会打印两者Exiting
,而Hello
捕获 EXITExiting
只会打印,但带有额外的换行符:
$ ./trapping-int
^CExiting
Hello
$ ./trapping-exit
^CExiting
$
我想知道不同行为的原因。另外,我可以安全地假设即使 ^C 给出了 INT 也总是调用 EXIT 吗?
注释掉两个脚本中的最后一行会导致捕获 SIGINT 不再打印 Hello,但捕获 EXIT 仍会打印额外的换行符。我也想知道这里的原因。
谢谢!
答案1
首先,总结一下有关信号和 shell 的一些事实:
当您按键盘上的 CTRL+C 时,SIGINT 会发送到前台进程的进程组中的所有进程。在这种情况下,这意味着
cat
命令和bash
解释脚本的进程都会收到 SIGINT 。当您 trap 时
INT
, anINT
将不再导致进程退出,除非您在处理程序中显式退出。当您 trap 时
EXIT
,您的参数不是在特定信号上运行,而是在 shell 退出时运行。
鉴于这些事实,的行为 trapping-int.sh
很简单,因为我们知道会发生以下情况:
- 进程
cat
收到 SIGINT 并终止其执行。 - 该
bash
进程接收 SIGINT 并运行其信号处理程序,将“Exiting\n”打印到STDOUT
。 - 该
bash
进程继续执行,并将“Hello\n”打印到STDOUT
。 - 该
bash
进程在到达脚本末尾时退出。
的行为trapping-exit.sh
也大多很简单:
- 进程
cat
收到 SIGINT 并终止其执行。 - 该
bash
进程收到一个 SIGINT,并且由于没有信号处理程序,它也会退出。它/不/运行该echo
命令,因为它在收到信号后立即退出。 - 由于
bash
进程正在退出,因此EXIT
处理程序将运行,并将“Exiting\n”打印到STDOUT
。
剩下的问题是“换行符从哪里来?”我相信正在发生的事情是 bash 本身正在安装一个SIGINT
打印换行符的处理程序。
在您的trapping-int.sh
脚本中,您覆盖 Bash 的处理程序SIGINT
,因此您不会获得额外的换行符。