有时,当我想快速注销时,我会这样做kill -15 -1
。我注意到 bash 忽略了 SIGTERM。
我想知道这种 bash 行为的理由是什么?
没有充分理由就忽略 SIGTERM 不是很 UNIX,不是吗?
更新:
对所有人都有相同(无)效果:
$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$
Run Code Online (Sandbox Code Playgroud)
更新2:
从人 bash:
当 bash 是交互式的,在没有任何陷阱的情况下,它会忽略 SIGTERM
所以这是故意的。但为什么?
Gil*_*il' 11
首先,这不是 bash 特有的。ATT ksh、dash 和 zsh 的行为方式相同:它们在命令行版本中忽略 SIGTERM 和 SIGQUIT;至于 mksh,它也不会退出,而是像 SIGINT 一样对待它们。
ksh 手册和 bash 手册都证明在这些方面忽略 SIGTERM 是合理的:
这样
kill 0
就不会杀死交互式 shell
kill 0
杀死shell 所在进程组中的所有进程¹。简而言之,进程组由在终端前台运行的所有进程,或在后台或挂起作业中的所有进程组成。
更准确地说,这就是具有作业控制功能的现代 shell 中发生的情况。在这样的 shell 中,kill 0
没有用,因为 shell 将在它自己的进程组中。较旧的 shell(或之后的现代 shell set +m
)没有为后台命令创建进程组。因此,您可以使用该命令kill 0
在不注销的情况下终止所有后台命令。² 因此,kill 0
基本原理看起来像一个旧的,现在不再合理,但保留了向后兼容性。
然而,在其他类似的情况下,使外壳免疫是有用的。考虑一下您有进程占用终端并且您想在不注销的情况下杀死它们的情况。许多系统都有类似的工具pkill
,可以让您终止在终端上运行的进程。您可以运行pkill -t $TTY
或pkill -QUIT -t $TTY
终止当前终端上正在运行的所有进程,但忽略信号的 shell 除外。
shell 通常会在用户退出时(使用类似exit
或的命令logout
)或终端发出输入结束信号(用户可以通过按Ctrl+引起这种情况D)或完全消失时消失。在最后一种情况下,shell 接收信号 SIGHUP,并且不会忽略该信号。
对于您注销 X 会话的用例,kill -15 -1
会这样做,因为它会杀死导致 shell 接收 SIGHUP 的终端模拟器。这实际上足以杀死 X 服务器,但这需要找到它的进程 ID。如果您希望在文本会话中使用相同的命令,您可以使用kill -15 -1; exit
. 无论如何,这是一个非常危险的命令。
¹通常,shell 手册中似乎没有提到这一点;这是底层系统调用的一个特性。它在POSIX 规范中明确提及。
²如今,要做到这一点,请运行jobs -l
以查看带有进程组 ID 的作业列表,然后kill -123 -456 …
杀死进程组。
小智 5
这可能会回答您的问题:
当 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。
如果 huponexit shell 选项已使用 shopt 设置(请参阅 Shopt 内置),则当交互式登录 shell 退出时,Bash 会向所有作业发送 SIGHUP。
如果 Bash 正在等待命令完成并接收到设置了陷阱的信号,则在命令完成之前不会执行陷阱。当 Bash 通过 wait 内置函数等待异步命令时,接收到设置了陷阱的信号将导致 wait 内置函数立即返回,退出状态大于 128,然后立即执行陷阱。
来源:GNU Bash 手册