为什么 bash 忽略 SIGTERM?

为什么 bash 忽略 SIGTERM?

有时当我想快速注销时我就会这样做kill -15 -1。我注意到 bash 忽略了 SIGTERM。

我想知道这种 bash 行为的理由是什么

如果没有充分的理由就忽略 SIGTERM,这不太符合 UNIX 风格,不是吗?

更新:

对所有人都有相同(无)影响:

$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$

更新2:

男人狂欢:

当 bash 是交互式的时,在没有任何陷阱的情况下,它会忽略 SIGTERM

所以这是故意的。但为什么?

答案1

首先,这不是 bash 特有的。 ATT ksh、dash 和 zsh 的行为方式相同:它们在命令行编辑期间忽略 SIGTERM 和 SIGQUIT;至于 mksh,它也不会退出,而是将它们视为 SIGINT。

ksh 手册和 bash 手册都证明在这些术语中忽略 SIGTERM 是合理的:

这样kill 0就不会杀死交互式 shell

kill 0杀死所有进程进程组外壳位于 1 中。简而言之,进程组由终端前台运行的所有进程,或者后台或挂起作业的所有进程组成。

更准确地说,这就是现代 shell 中发生的情况作业控制。在这样的 shell 中,kill 0没有用,因为 shell 将位于它自己的进程组中。较旧的 shell(或之后的现代 shell)set +m)没有为后台命令创建进程组。因此,您可以使用该命令kill 0来终止所有后台命令,而无需注销。² 因此,其kill 0基本原理看起来像旧的,现在不再合理,但保留了向后兼容性。

然而,在其他类似的情况下,使外壳免疫是有用的。考虑这样一种情况:您有进程占用终端,并且您希望在不注销的情况下杀死它们。许多系统都有类似的工具pkill它可以让你杀死终端上运行的进程。您可以运行pkill -t $TTYpkill -QUIT -t $TTY终止当前终端上运行的所有进程,忽略信号的 shell 除外。

shell 通常会在用户退出它时消失(使用类似exit或 的命令logout),或者当其终端发出输入结束信号时(用户可以通过按Ctrl+来导致此情况D)或完全消失。在最后一种情况下,shell 收到信号 SIGHUP,并且它不会忽略该信号。

对于注销 X 会话的用例,kill -15 -1将执行此操作,因为它会杀死导致 shell 接收 SIGHUP 的终端仿真器。事实上,杀死 X 服务器就足够了,但这需要找到它的进程 ID。如果您希望在文本会话中使用相同的命令,则可以使用kill -15 -1; exit.无论如何,这是一个相当危险的命令。

1通常 shell 手册中似乎没有提到这一点;这是底层系统调用的一个功能。中明确提到了POSIX规范
²如今,要做到这一点,请运行jobs -l查看作业列表及其进程组 ID,然后kill -123 -456 …终止进程组。

答案2

这可能会回答你的问题:

当 Bash 是交互式的时,在没有任何陷阱的情况下,它会忽略 SIGTERM(因此“kill 0”不会杀死交互式 shell),并且 SIGINT 会被捕获并处理(以便 wait 内置命令是可中断的)。当 Bash 收到 SIGINT 时,它会中断任何正在执行的循环。在所有情况下,Bash 都会忽略 SIGQUIT。如果作业控制有效(请参阅作业控制),Bash 会忽略 SIGTTIN、SIGTTOU 和 SIGTSTP。

Bash 启动的非内置命令将信号处理程序设置为 shell 从其父级继承的值。当作业控制无效时,除了这些继承的处理程序之外,异步命令还会忽略 SIGINT 和 SIGQUIT。由于命令替换而运行的命令会忽略键盘生成的作业控制信号 SIGTTIN、SIGTTOU 和 SIGTSTP。

默认情况下,shell 在收到 SIGHUP 后退出。在退出之前,交互式 shell 会向所有正在运行或已停止的作业重新发送 SIGHUP。停止的作业将被发送 SIGCONT 以确保它们收到 SIGHUP。为了防止 shell 向特定作业发送 SIGHUP 信号,应使用 disown 内置函数将其从作业表中删除(请参阅作业控制内置函数),或使用 disown -h 将其标记为不接收 SIGHUP。

如果已使用 shopt 设置了 huponexit shell 选项(请参阅 Shopt 内置),则当交互式登录 shell 退出时,Bash 会向所有作业发送 SIGHUP。

如果 Bash 正在等待命令完成并接收到已设置陷阱的信号,则在命令完成之前不会执行陷阱。当 Bash 通过 wait 内置函数等待异步命令时,接收到已设置陷阱的信号将导致 wait 内置函数立即返回,退出状态大于 128,然后立即执行陷阱。

来源:GNU Bash 手册

相关内容