写点什么

linux 系列之: 告诉他,他根本不懂 kill

发布于: 1 小时前

简介

和很多程序员打过交道,这些程序员可能熟知 for 遍历的好几种写法,但是却对写出来的程序部署的环境一无所知。我敢打赌,在 spring boot 出现之后,已经很少有程序员知道 tomcat 到底是怎么运行的了。对于他们来说,运行一个 jar 包就完事了。

工具的先进性确实带给我们很多便利,也提升了程序员的开发效率,同时也降低了程序员的进入门槛。今天想和大家一起讨论一下,linux 中的 kill 命令到底是做什么用的。

可能很很多小伙伴第一次接触 kill 命令是同事告诉他,把进程 kill 掉。那么 kill 真的是用来杀进程的吗?

使用 kill 来杀死进程

先来看一个 kill 最基本,也是最常见的应用就是杀死进程。在杀死进程之前,我们需要找到这个进程 ID。

一般情况下是使用 ps 命令找到这个进程 ID。加入这个进程 ID=54321。

那么接下来就可以使用 kill 54321 来杀死这个进程了。

更资深一点的同学,可能还会使用 kill -9 54321 来强制杀死这个进程。

有没有更深入的用法呢?有的,一起来看看。

kill 的深入用法

先看一下 kill 的命令参数到底有那些:

kill kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
复制代码

可以看到 kill 的参数是 sig,也就是信号。也就是说 kill 的本质是向程序传递信号的。

如果使用 kill -l ,我们可以得到到底 kill 可以传递多少信号:

kill -l  1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR111) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+338) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+843) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-758) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-263) SIGRTMAX-1  64) SIGRTMAX
复制代码

总共 64 个信号,可能不同的 kill 版本,信号有所不同,但是基本上都覆盖了常用的信号。

下面是一些常用信号的含义:

HUP     1    终端断线INT       2    中断(同 Ctrl + C)QUIT    3    退出(同 Ctrl + \)TERM    15    终止KILL      9    强制终止CONT   18    继续(与STOP相反, fg/bg命令)STOP    19    暂停(同 Ctrl + Z)
复制代码

怎么看 kill 的版本呢?

/bin/kill --versionkill from util-linux 2.23.2
复制代码

如果 kill 不传 sig,那么将会传默认的 sig=TERM,也就是 15。所以上面的 kill 54321 和 kill -15 54321 是等价的。

一般情况下,我们优先使用 SIGTERM 信号。这是因为当程序收到了 SIGTERM 信号之后,会做一些程序的清理操作,或者说是优雅的关闭。

如果传入 kill -9 也就是 SIGKILL,那么应用程序将无法捕捉这个信号,从而导致程序强制被关闭,有可能会照成一些异常情况,比如数据还没有保存,数据传输还没有结束等等。

sig 还有一个特殊值叫做 0,如果传入 0 的话,那么并不会发送实际的信号,这个只是做异常检测用的。

pid 就是 process id,可以理解为是进程号。除了进程号之外,还可以传入一些特殊值,比如:

  • 0 表示当前进程 group 的所有进程

  • -1 表示所有 PID>1 的进程

还有一个特殊的 pid=1,这个 pid 表示的是初始进程 init,这个进程是不可被杀死的。

除了 PID 之外,我们看到 kill 还可以接受 jobspec。job id 可以使用 jobs 命令来列出。

僵尸进程和 kill

上面讲到了 pid=1 的初始进程是不能被 kill 的。还有一种不能被 kill 的进程叫做僵尸进程。

僵尸进程是 linux 程序中一个非常独特的状态,它表示的是进程已经结束了,但是又还没有完全死亡,就像僵尸一样。

linux 中的 5 大进程状态分别是:RUNNING:正在运行或等待运行状态,UNINTERRUPTABLE:不可中断阻塞状态,INTERRUPTABLE:可中断阻塞状态,STOPPED:挂起状态和 ZOMBIE:僵尸状态。

那么什么是僵尸进程呢?

僵尸进程指的是程序在退出之后,该进程并不是马上消失的,而是会保留一个被称为僵尸的数据结构。这个数据结构很特殊,因为其没有内存空间,没有可执行的代码,当然也不可以被调度。它只是在进程列表中占有一个位置,记录了该进程退出时候的各种信息。

僵尸进程主要是保留进程退出的现场,供父进程或者系统管理员进行分析使用的,所以僵尸进程是交由父进程来进行收集和释放的。因为僵尸进程已经退出了,所以使用 kill 是没有用的,只能等待其父进程退出,才能真正的退出。

怎么查看僵尸进程呢?最简单的方法就是使用 top 命令:

top - 14:34:38 up 305 days,  4:23,  2 users,  load average: 0.20, 0.29, 0.47Tasks:  93 total,   1 running,  92 sleeping,   0 stopped,   0 zombie%Cpu(s):  2.0 us,  0.7 sy,  0.0 ni, 97.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 stKiB Mem :  1882008 total,   525524 free,   311440 used,  1045044 buff/cacheKiB Swap:        0 total,        0 free,        0 used.  1382560 avail Mem 
复制代码

上面的输出,我们可以看到里面有 0 个 zombie。

java thread dump

kill 还有一个非常有用的地方就是生成 java 程序的 thread dump,将当前 java 程序的线程信息 dump 出来,可以进行一些有用的分析,比如死锁分析等。

怎么对 java 进程做 thread dump 呢?很简单使用 kill -3 命令即可:

kill -3 <pid>
复制代码

从上面我们的介绍可以指定 3 代表的信号是 SIGQUIT。这说明 JVM 内置了这个信号的捕捉,如果接收到了这个信号,则会 dump 当前的线程信息。

java thread dump 在对 java 进行线程分析的时候非常有用。

总结

本文介绍了 kill 的深入用法和底层的工作原理,还介绍了 kill 的几个应用,希望下次有人再问你 kill 到底是什么的时候,大家都可以很自豪的告诉他!

本文已收录于 http://www.flydean.com/01-that-is-kill/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 1 小时前阅读数: 2
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
linux系列之:告诉他,他根本不懂kill