我有一个无法用kill -9 <pid>杀死的进程。在这种情况下有什么问题,尤其是因为我是该过程的所有者。我以为kill选项无法回避。

#1 楼

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

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

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

被系统调用阻塞的进程处于不间断的睡眠状态。 pstop命令将(在大多数unices上)以状态D(我认为最初是“磁盘”)显示它。服务器没有响应;现代的实现往往不会强加不间断的睡眠(例如,在Linux下,intr挂载选项允许信号中断NFS文件访问)。

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

评论


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

– jlliagre
2011年1月11日12:27



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

–吉尔斯'所以-不再是邪恶的'
2011年1月11日在20:07

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

– jlliagre
2011年1月11日在21:39

man 5 nfs:“在内核2.6.25之后不建议使用intr / nointr挂载选项。只有SIGKILL可以中断这些内核上的挂起的NFS操作,如果指定,则忽略此挂载选项以提供与较早内核的向后兼容性。”

–马丁·施罗德(MartinSchröder)
2012年8月7日在20:05

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

–吉尔斯'所以-不再是邪恶的'
13年3月28日在19:42

#2 楼

某个进程存在,由于以下原因而无法杀死:


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


评论


僵尸不消耗资源吗?

–Luc M
2011年1月11日下午4:17

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

– Maciej Piechotka
2011年1月11日,下午5:16

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

– Maciej Piechotka
2011年1月11日上午10:13

“ ...唯一的方法是重新启动或等待。”等待多长时间?五个月过去了,我的僵尸仍然在那里。

– DarenW
2015年4月14日在4:10

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

– Maciej Piechotka
16年1月16日下午5:35

#3 楼

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

通过使用top或以下命令,可以查看该进程是否是僵尸:

ps aux | awk '=="Z" {print }'


评论


嗯,我总是不喜欢ps这种“硬”字段名。谁能确定在所有Unices中ps的所有实现中,必填字段将始终为8?

–syntaxerror
2015年2月7日在17:15



POSIX并未为ps定义stat字段,因此无法编写适用于所有Unices的命令。您能做的最接近的是ps -o pid,stat | awk'/ Z / {print $ 1}'

– Mikko Rantalainen
5月14日18:09

#4 楼

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

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

评论


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

– Stefan Lasiewski
2011年1月11日在17:02

#5 楼

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

评论


我猜想许多rootkit会将自己插入内核以简化操作(无需猜测用户拥有什么并下载MB的修补程序)。但是,仍然值得检查(++投票)。

– Maciej Piechotka
2011年1月12日22:12

#6 楼

首先,检查其是否具有Zombie进程(非常有可能): >
(请注意左侧的“ Z”)

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

如果其PPID = 1,请不要杀!!,请考虑可能与之相关的其他设备或进程。

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

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

评论


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

–斯蒂芬妮
2014年1月21日,11:21

即使PPID不为1,仍然值得用ps -ef |检查父进程是什么以及父进程是哪些其他进程。 grep N其中N是相关的PPID。一般来说,这是个好主意,尤其是自从引入子收割器(早在2012年)以来,尤其是在使用使用systemd的发行版的情况下。

–克里斯·亨利(Chris Henry)
3月5日下午16:53

#7 楼

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

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

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

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

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

评论


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

– JoelFan
2011年1月11日下午5:53

#8 楼

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

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

评论


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

– imz-伊万·扎哈拉里舍夫(Ivan Zakharyaschev)
13年3月28日在14:57

@imz那里有Gilles的建议(杀死sshfs)-unix.stackexchange.com/a/5648/4319。

– imz-伊万·扎哈拉里舍夫(Ivan Zakharyaschev)
13年3月30日在12:36

#9 楼



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

评论


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

–东武
13年2月28日在10:37

#10 楼

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

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

 #!/bin/bash

if [ "" == "-u" ] ; then\n
        PID=`grep "" /etc/passwd | cut -d ":" -f3`
        processes=`ps aux | grep "$PID" | egrep -v "PID|ps \-au|killbyname|grep" | awk '{ print }'`
        echo "############# Killing all processes of user:  ############################"
else
        echo "############# Killing processes by name:  ############################"
        processes=`ps aux | grep "" | egrep -v "killbyname|grep" | awk '{ print }' `
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  }'`
        echo "Killing process: $process"
        echo ""
        kill -9 $process
done
 


评论


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

– tshepang
13年3月27日在20:53

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

– vonbrand
13年3月27日在21:23

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

–user36035
13年4月1日在17:43

#11 楼

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

评论


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

– tshepang
2011年1月11日23:19

#12 楼

从这里开始:

检查strace是否显示任何内容

strace -p <PID>


尝试使用gdb附加到进程

gdb <path to binary> <PID>


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

评论


为我工作! (拔出挂有升华文字的USB设备)

–nmz787
17年3月19日在18:18

#13 楼

我有点这个问题。这是我使用strace启动并被Ctrl + C打断的程序。它最终以T(跟踪或停止)状态运行。我不知道它到底是怎么发生的,但是不能用SIGKILL杀死。

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

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


#14 楼

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

所以在我看来,它是僵尸,但仍在消耗资源... FWIW。 />并且它不能被任何数量的init杀死

,它的父代是kill -9,但是没有被收割(清理)。即init有一个僵尸孩子。

,无需重新启动即可解决此问题。虽然重启将“解决问题” /使其更快地关机。只是不优雅,这仍然可能。

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

上面提到的很多

结果发现我内部有一个线程正在执行一个“系统调用”(在这种情况下为ioctl),这花费了几个小时才能完成。返回(这是预期的行为)。显然,系统无法完全杀死进程,直到它从init调用返回为止,猜测它已进入内核。几个小时后,它恢复了正常,清理了所有东西,插座全部自动关闭,依此类推。那是在死囚牢里的苦日子!内核正在耐心地等待杀死它。

因此,要回答OP,有时必须等待。很长时间。然后最终将消灭一切。

还要检查dmesg以查看是否存在内核恐慌(即内核错误)。

评论


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

–世纪
19年7月8日在18:54

没错,我添加了它如何响应OP,因为在某些情况下可以。

–rogerdpack
19年7月8日在19:08