bash在 Kubuntu Trusty 64 位上运行4.3。请看以下两个文件:
捕获-int.sh
#! /bin/bash
trap "echo Exiting" INT
cat </dev/urandom >/dev/null
echo Hello
Run Code Online (Sandbox Code Playgroud)
诱捕exit.sh
#! /bin/bash
trap "echo Exiting" EXIT
cat </dev/urandom >/dev/null
echo Hello
Run Code Online (Sandbox Code Playgroud)
现在,在点击 ^C 时,捕获 SIGINT 会同时打印两者Exiting,Hello而捕获 EXITExiting只会打印但带有额外的换行符:
$ ./trapping-int
^CExiting
Hello
$ ./trapping-exit
^CExiting
$
Run Code Online (Sandbox Code Playgroud)
我想知道不同行为的原因。另外,我可以安全地假设即使 INT 是由 ^C 给出的,也总是会调用 EXIT 吗?
注释掉两个脚本中的最后一行会导致捕获 SIGINT 不再打印 Hello,但捕获 EXIT 仍会打印额外的换行符。我也想知道这里的原因。
谢谢!
Ste*_*n D 11
首先,总结一下有关信号和外壳的一些事实:
当您在键盘上按 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,因此您不会获得额外的换行符。