如果“ kill -9”不起作用怎么办?


467

我有一个我不能杀死的过程kill -9 <pid>。在这种情况下有什么问题,尤其是因为我是该过程的所有者。我认为没有什么可以回避这种kill选择。

Answers:


561

kill -9SIGKILL)始终有效,只要您有权终止该过程即可。基本上,该过程必须由您启动而不是setuid或setgid,或者您必须是root用户。有一个例外:即使root也无法向PID 1发送致命信号(该init过程)。

但是kill -9不能保证立即工作。包括SIGKILL在内的所有信号都是异步传递的:内核可能会花一些时间来传递它们。通常,传递信号最多需要几微秒的时间,这恰好是目标获得时间片的时间。但是,如果目标已阻止信号,则该信号将排队,直到目标取消阻止为止。

通常,进程无法阻止SIGKILL。但是,内核代码可以并且进程在调用系统调用时执行内核代码。当中断系统调用时,内核代码会阻塞所有信号,从而导致内核中某个地方的数据结构格式错误,或更常见的是会破坏某些内核不变式。因此,如果(由于错误或错误设计)系统调用无限期地阻塞,则可能实际上没有办法终止该过程。(但是,如果该进程完成了系统调用,它将被杀死。)

系统调用中阻塞的进程处于不间断的睡眠状态。该pstop命令(在大多数Unix系统)显示它的状态D(原本为“ d ISK”,我认为)。

长时间不间断睡眠的典型情况是,当服务器没有响应时,进程将通过NFS访问文件。现代的实现往往不会强加不间断的睡眠(例如,在Linux下,intrmount选项允许信号中断NFS文件访问)。

有时您可能会在或输出中看到带有标记的条目Z(或者H在Linux下,我不知道区别是什么)。从技术上讲,这些进程不是僵尸进程,它们只是进程表中的一个条目而已,它们始终保留在进程表中,以便可以将其子进程的死亡通知父进程。当父进程关注(或死亡)时,它们将消失。pstop


92
您的回复看起来很矛盾。您开始告诉SIGKILL总是可以工作,但最后以不间断的睡眠方式为例,在这种情况下,SIGKILL在关闭内核之前可能永远无法工作。在两种情况下,SIGKILL不起作用。显然,对于僵尸来说,您无法杀死已经死掉的进程,而对于init,通过设计,它会忽略SIGKILL信号。
jlliagre 2011年

41
@jlliagre:杀死僵尸没有任何意义,从一开始就没有生命。在可中断的睡眠杀死一个进程确实有效,就像(与其他信号一样)异步。我尝试在编辑中澄清这一点。
吉尔斯

3
我写过杀死一个僵尸也没有道理,但这并不能阻止许多人尝试它并抱怨。在可中断睡眠中杀死进程确实是设计使然,但我所谈论的是在不间断睡眠中杀死进程,如果系统调用永不唤醒,则该进程将失败。
jlliagre 2011年

11
man 5 nfs:“ intr/ nointrmount选项在内核2.6.25之后不推荐使用。只有SIGKILL可以中断这些内核上的挂起的NFS操作,如果指定,则忽略此mount选项以提供与旧内核的向后兼容性。”
MartinSchröder2012年

4
@ imz--IvanZakharyaschev我不知道(但是我可能不知道)。作为最后的手段,使用sshfs可以终止sshfs进程(同样,对于任何其他FUSE文件系统:您也可以始终以这种方式强制卸载)。
吉尔斯2013年

100

有时存在进程,由于以下原因无法将其杀死:

  • 僵尸。即处理哪个父母没有读取退出状态。除了PID输入之外,该过程不会消耗任何资源。在top信号Z
  • 错误的不间断睡眠。它应该不会发生,但有时会结合错误的内核代码和/或错误的硬件。唯一的方法是重新启动或等待。在top其中由D发出信号。

2
僵尸不消耗资源吗?
卢克M

7
@Luc M:AFAIK否(至少在Linux上是)-进程表中的条目(即PID以及所有者,退出状态等信息)除外。只是等待对方终止确认的过程。
Maciej Piechotka 2011年

18
@xenoterracide:最终是的,但是如果父进程仍然存在(例如,它是gnome-session或完全扮演类似角色的东西),您可能还会有僵尸。从技术上讲,清理工作是父母的工作,但是如果僵尸成为孤儿,则init会清理它(术语是unix类闭门造车的原因-任何听说过孤儿,僵尸和一句话杀人的人都会有错误的印象)。
Maciej Piechotka,2011年

5
“ ...唯一的方法是重新启动或等待。”等待多长时间?五个月过去了,我的僵尸还在。
DarenW 2015年

3
@DarenW,直到父母确认孩子死亡为止。有关详细信息,请询问程序的作者。
Maciej Piechotka '16

32

听起来您可能遇到了僵尸进程。这是无害的:僵尸进程消耗的唯一资源是进程表中的一个条目。当父进程死亡或对其子进程的死亡做出反应时,它将消失。

您可以使用top或以下命令查看进程是否为僵尸:

ps aux | awk '$8=="Z" {print $2}'

13
嗯,我总是不喜欢这种“硬”字段名称ps。谁能确保所有Unices的所有实现的必填字段始终为8 ps
语法错误,2015年

26

检查您/var/log/kern.log/var/log/dmesg(或同等学历)是否有任何线索。以我的经验,这仅在NFS挂载的网络连接突然断开或设备驱动程序崩溃时才发生。我相信,如果硬盘驱动器也崩溃,可能会发生。

您可以lsof用来查看进程打开了哪些设备文件。


6
+1提及NFS。几年前,这种情况每隔几个月就发生在我身上-如果NFS服务器崩溃,则所有(已修补)RHEL盒上的NFS客户端都会挂起。kill -9通常即使在等待60分钟后仍无法正常工作。唯一的解决方案是重新启动。
Stefan Lasiewski 2011年

17

如果@ Maciej和@ Gilles的答案不能解决您的问题,并且您不认识该过程(并且询问发行版的内容也不会给出答案)。检查Rootkit以及您拥有的其他任何符号。Rootkit能够阻止您终止进程。实际上,许多功能都可以阻止您看到它们。但是,如果他们忘记修改1个小程序,它们可能会被发现(例如,他们修改了top,但没有htop)。很有可能不是这种情况,但是比后悔更安全。


我猜想许多rootkit会将其自身插入内核以使事情变得更简单(无需猜测用户拥有什么并下载MB的修补程序)。但是,仍然值得检查(++投票)。
Maciej Piechotka 2011年

11

杀死实际上意味着发出信号。您可以发送多个信号。kill -9是一个特殊信号。

发送信号时,应用程序将对其进行处理。如果不是,内核会处理它。因此您可以在应用程序中捕获信号。

但是我说杀死-9很特别。特殊之处在于应用程序无法获取它。它直接进入内核,然后在第一个可能的机会中真正杀死应用程序。换句话说杀死了它

kill -15发送代表信号终止的信号SIGTERM,换句话说,告诉应用程序退出。这是一种告诉应用程序该关闭的友好方式。但是如果应用程序没有响应,则kill -9将杀死它。

如果kill -9不起作用,则可能意味着您的内核已无法使用。重新启动是正常的。我不记得曾经发生过的事。


5
15是SIGTERM(友善杀死),而不是SIGHUP。SIGHUP用于控制终端关闭或通信通道丢失
JoelFan 2011年

11

首先,检查其是否为僵尸进程(这很有可能):

ps -Al

您将看到类似以下内容:

0 Z  1000 24589     1  0  80   0 -     0 exit   ?        00:00:00 soffice.bin <defunct>

(请注意左侧的“ Z”)

如果第5列不是1,则表示它具有父进程。 尝试杀死该父进程id

如果其PPID = 1,请不要杀!,请考虑哪些其他设备或进程可能与此有关。

例如,如果您使用的是已安装的设备或samba,请尝试将其卸载。那可能会释放僵尸进程。

注意:如果ps -Al(或top)显示的是“ D”而不是“ Z”,则可能与远程安装(如NFS)有关。以我的经验,重新启动是到达那里的唯一方法,但是您可以检查涵盖该情况的其他答案。


1
将SIGCHLD发送到父进程可能会使父进程识别该进程已死亡。即使PPID = 1,这也应该起作用。通常由内核发送,但是也可以通过kill一起发送给父进程(在Linux上为kill -17,请在其他* nix上查看联机帮助页)。这种杀戮的使用实际上并不会“杀死”父母,而是(重新)通知它孩子已经死了,需要清理。请注意,必须将sigchld发送给僵尸的父级,而不是僵尸本身。
Stephanie 2014年

10

初始化过程不受SIGKILL的影响。

对于内核线程,即PPID等于0的“进程”,也是如此。


1
内核任务也可以不受SIGKILL的影响。Btrfs经常发生这种情况。
东武

9

正如其他人提到的那样,不间断睡眠的过程无法立即被杀死(或在某些情况下根本无法杀死)。值得注意的是,在某些情况下,特别是在进程正在等待NFS的常见情况下,添加了另一个进程状态TASK_KILLABLE来解决此问题。参见http://lwn.net/Articles/288056/

不幸的是,除了NFS,我不相信这会在内核的任何地方使用。


当远程服务器无法访问时,我在杀死ls访问sshfs安装的进程时遇到了问题。是否有针对FUSE或sshfs的解决方案,以后可以用来避免这种情况?2.6.30内核
imz – Ivan Zakharyaschev


6

制作了一个小脚本,对我有很大帮助!

您可以使用它杀死路径中具有给定名称的任何进程(请注意!!),也可以使用“ -u username”参数杀死给定用户的任何进程。

#!/bin/bash

if [ "$1" == "-u" ] ; then\n
        PID=`grep "$2" /etc/passwd | cut -d ":" -f3`
        processes=`ps aux | grep "$PID" | egrep -v "PID|ps \-au|killbyname|grep" | awk '{ print $2}'`
        echo "############# Killing all processes of user: $2 ############################"
else
        echo "############# Killing processes by name: $1 ############################"
        processes=`ps aux | grep "$1" | egrep -v "killbyname|grep" | awk '{ print $2}' `
fi


for process in $processes ; do
        # "command" stores the entire commandline of the process that will be killed
        #it may be useful to show it but in some cases it is counter-productive
        #command=`ps aux | grep $process | egrep -v "grep" | awk '{ print $2 }'`
        echo "Killing process: $process"
        echo ""
        kill -9 $process
done

4
您不仅可以链接到它,还可以在这里发布代码。
tshepang

3
用(或至少代替)代码添加一些描述...
vonbrand

是的,但是“ $ name”更加聚合了...它将杀死运行路径中带有“ $ name”的任何进程。如果您拥有这些巨大的命令行并且不知道进程名称是什么,可能会非常有用。
user36035

5

在某些情况下,即使向进程发送kill -9,该pid也会停止,但是该进程会自动重新启动(例如,如果使用尝试gnome-panel,它将重新启动):在这种情况下可以吗?


8
当发生这种情况时,PID实际上会更改。所以我会注意到的。
tshepang 2011年

2

这里开始

检查strace是否显示任何内容

strace -p <PID>

尝试使用gdb附加到进程

gdb <path to binary> <PID>

如果该进程正在与您可以卸载的设备进行交互,请删除其内核模块,或以物理方式断开/拔出...然后尝试该操作。


为我工作!(拔出悬挂着高
品质

1

我有点这个问题。这是我straceCtrl+ 启动并中断的程序C。它最终处于T(跟踪或停止)状态。我不知道它是怎么发生的,但是用不能杀死它SIGKILL

长话短说,我成功杀死了它gdb

gdb -p <PID>
> kill
Kill the program being debugged? (y or n) y
> quit

-1

根据吉勒斯回答的线索,我在进程<defunct>中使用系统资源的顶部(以ps为单位)标有“ Z” ,它甚至有一个正在监听的端口,您可以连接到该端口。这是在执行了之后kill -9。它的父init代为“ 1”(即),因此从理论上讲,它应该被废除并消失。但事实并非如此,它虽然没有在奔跑,但仍在附近徘徊,并“不死”

因此,就我而言,这是僵尸,但仍在消耗资源... FWIW。

而且它不能被任何数量kill -9

它的父对象是,init但是没有被收割(清理)。即生init了一个僵尸孩子。

重新启动不是解决该问题所必需的。尽管重启将“解决问题” /使其更快地关机。只是不优雅,这仍然是可能的。

这是僵尸进程拥有的LISTEN端口(还有一些其他端口,例如CLOSE_WAIT status将localhost连接到localhost)。而且它甚至仍然接受连接。即使是僵尸。我想它还没有清理端口,因此尽管没有被接受的机会,传入的连接仍被添加到tcp侦听端口的待办事项中。

上面的许多内容在互连网上的各个位置被声明为“不可能”。

事实证明,我内部有一个线程正在执行“系统调用”(在本例中为ioctl),这需要花费几个小时才能返回(这是预期的行为)。显然,系统无法从进程中完全终止进程,直到它从ioctl调用中返回为止,猜测它已进入内核区域。几个小时后,它恢复了原状,插座全部自动关闭,依此类推。那是在死囚牢里的苦日子!内核正在耐心地等待杀死它。

因此,要回答OP,有时必须等待。很长时间。然后最终将被杀死。

还要检查dmesg,看看是否有内核崩溃(即内核错误)。


这似乎是您在描述自己的特定情况,而不是问题的答案。在您的情况下,由于长时间运行,该过程自行修复,问题中未提及。但是,欢迎您提出新问题并提供答案。尽管我担心这个问题可能会以“不可复制”的形式结束,因为结果是特定于您的实现的。
Centimane

没错,我添加了它如何响应OP,因为在某些情况下可以。
rogerdpack
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.