分析并解决 kill -9 pid 无效的问题

问题概述

由于本人不良的 coding 习惯,debug 的时候常常用 ctrl+z 终止运行,造成很多僵尸进程占用服务器内存。。。所以 kill -9 pid 就是常规操作。但是最近 kill -9 pid 经常无效,因此花了点时间研究这玩意。

预备知识

关于 kill 指令

Linux kill 命令用于删除执行中的程序或工作。

kill 可将指定的信息送至程序。预设的信息为 SIGTERM(15),可将指定程序终止。若仍无法终止该程序,可使用 SIGKILL(9) 信息尝试强制删除程序。程序或工作的编号可利用 ps 指令或 jobs 指令查看。

kill的命令参数有以下几种:
-l 信号,若果不加信号的编号参数,则使用“-l”参数会列出全部的信号名称
-a 当处理当前进程时,不限制命令名和进程号的对应关系
-p 指定kill 命令只打印相关进程的进程号,而不发送任何信号
-s 指定发送信号
-u 指定用户

信号如果没有指定的话,默认会发出终止信号(15)。常用的信号如下:
HUP 1 终端断线
INT 2 中断(同 Ctrl + C)
QUIT 3 退出(同 Ctrl + \)
TERM 15 终止
KILL 9 强制终止
CONT 18 继续(与STOP相反, fg/bg命令)
STOP 19 暂停(同 Ctrl + Z)

举个栗子

杀死进程
kill 12345
强制杀死进程
kill -KILL 123456
发送SIGHUP信号,可以使用一下信号
kill -HUP pid
彻底杀死进程
kill -9 123456

kill -9 pid 失效的情况

kill -9 并非无所不能,在遇到以下两种情况时会失效。

1.该进程是僵尸进程(STAT z),此时进程已经释放所有的资源,但是没有被父进程释放。
僵尸进程要等到父进程结束,或者重启系统才可以被释放。

2.进程处于“内核态”,并且在等待不可获得的资源,处于“内核态 ”的资源默认忽略所有信号,只能重启系统解决。
进程在Linux 中会处于两种状态,即用户态和内核态。只有处于用户态的进程才可以用“kill”命令将其终止。

聊一下进程的几种状态

Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态。这里列个名字,记录一下。

  1. R (TASK_RUNNING),可执行状态。
  2. S (TASK_INTERRUPTIBLE),可中断的睡眠状态。
  3. D (TASK_UNINTERRUPTIBLE),不可中断的睡眠状态。
  4. T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态。
  5. Z (TASK_DEAD - EXIT_ZOMBIE),退出状态,进程成为僵尸进程。
  6. X (TASK_DEAD - EXIT_DEAD),退出状态,进程即将被销毁。

如何解决呢?

找到僵尸进程,kill 掉他的父进程即可。
用 ps 和 grep 命令寻找僵尸进程
ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'

命令注解:
-A 参数列出所有进程
-o 自定义输出字段 我们设定显示字段为 stat(状态), ppid(进程父id), pid(进程id),cmd(命令)这四个参数 因为状态为 z或者Z的进程为僵尸进程。

一点点个人操作

我在 kill 掉所有的僵尸进程之后,发现还是有几个没用的后台进程占用空间,但是他们确实不属于僵尸进程,用 kill -9 也没用。
后来我找到了所有的 T 进程,把看上去没用的 kill 掉,就解决了。

你可能感兴趣的:(linux)