问题概述
由于本人不良的 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是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态。这里列个名字,记录一下。
- R (TASK_RUNNING),可执行状态。
- S (TASK_INTERRUPTIBLE),可中断的睡眠状态。
- D (TASK_UNINTERRUPTIBLE),不可中断的睡眠状态。
- T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态。
- Z (TASK_DEAD - EXIT_ZOMBIE),退出状态,进程成为僵尸进程。
- 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 掉,就解决了。