为什么捕获 EXIT 与 INT 的行为不同

为什么捕获 EXIT 与 INT 的行为不同

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,因此您不会获得额外的换行符。

相关内容