首先,这并非专门针对bash。ATT ksh,dash和zsh的行为方式相同:在命令行编辑期间,它们忽略SIGTERM和SIGQUIT;至于mksh,它也不会退出,而是像SIGINT一样对待它们。
无论是ksh手册还是bash手册,在这些方面都可以忽略SIGTERM:
这样kill 0
不会杀死交互式外壳
kill 0
杀死外壳所在的进程组中的所有进程。简而言之,进程组由在终端上前台运行的所有进程,或在后台或挂起作业中的所有进程组成。
更确切地说,这是在具有作业控制功能的现代Shell中发生的情况。在这样的外壳中,kill 0
它将没有用,因为外壳将位于其自己的进程组中。较旧的外壳(或之后的现代外壳set +m
)未为后台命令创建进程组。因此,您可以使用该命令kill 0
杀死所有后台命令而无需注销。²因此,其kill 0
原理看起来像是一个旧的,如今不再合理,但为了向后兼容而保留。
但是,在其他类似情况下,使外壳具有免疫性也是有用的。请考虑以下情况:您有进程在占用终端,而您想杀死它们而不注销。许多系统都有类似的工具pkill
,可以让您杀死在终端上运行的进程。您可以运行pkill -t $TTY
或pkill -QUIT -t $TTY
杀死当前终端上正在运行的所有进程,但忽略信号的外壳除外。
通常,当用户退出外壳时(使用诸如exit
或的命令logout
),或者当外壳的终端发出输入信号结束时(用户可以通过按Ctrl+ 引起此情况),外壳就会消失D或完全消失。在最后一种情况下,shell接收到信号SIGHUP,并且它不会忽略该信号。
对于注销X会话的用例,kill -15 -1
将执行此操作,因为它会杀死导致外壳程序接收SIGHUP的终端仿真器。实际上足以杀死X服务器,但这需要找到其进程ID。如果要在文本会话中使用相同的命令,可以使用kill -15 -1; exit
。无论如何,这是一个非常危险的命令。
¹ 通常在shell手册中似乎没有提到这一点;这是基础系统调用的功能。它在POSIX规范中明确提到。
² 现在,要执行此操作,请运行jobs -l
以查看其进程组ID的作业列表,然后kill -123 -456 …
杀死进程组。
/bin/kill
还是内置的外壳?如果是后者,我猜测外壳将无法使用自己的内置功能杀死自己。