killall是干什么的?

7 年 ago jony killall是干什么的?已关闭评论

作者:守望,Linux应用开发者,目前在公众号【编程珠玑】 分享Linux/C/C++/数据结构与算法/工具等原创技术文章和学习资源。

前言

在Linux下有很多命令用于杀死进程,它们可以用于不同的场景,例如通过进程名杀死进程,通过pid杀死进程。这些方法我不准备一一列举,本文想说明的一个问题是,为什么明明通过ps找到了进程,但是通过killall却说找不到呢?如果你没有遇到过这样的问题?那你更要注意了!

killall简介

与kill不同的是,killall可以根据进程名来杀死进程,不像kill,可能先需要使用ps(可以参考《ps命令实例详解》)找到进程id,然后发送信号,就像下面这样:

$ ps -ef|grep helloroot      15530  6335  0 14:55 pts/4    00:00:00 ./hello$ kill -9 15530

这样进程就被我们杀死了,我们可以直接使用killall:

$ killall hello

是不是觉得方便多了?

而且由于killall是根据名称杀死进程,因此如果当前运行着大量的hello程序,那么可以一次性杀死所有hello程序。

除此之外,它还有很多参数,例如忽略大小写,根据模式匹配进程名,杀死某个时间的进程等等,这里就不详解介绍了,有兴趣的可以查看man killall手册。

今天这里想要说明的是一种killall失效的情况。

killall失效了?

我写了一个自己的hello程序,然后尝试使用killall杀死正在运行的hello程序。

$  killall hellohello: no process found

什么?竟然说找不到?一个ps丢过来:

$ ps -ef|grep helloroot      15765  6335  0 15:05 pts/4    00:00:00 ./hello

所以killall你到底行不行?

为何

为了找出killall失效的原因,我们必须知道它到底是如何通过进程名找到进程的。
这个时候就需要祭出我们的神器strace了,看看killall杀死一个普通进程到底做了哪些事情:

$ strace killall helloopen("/proc/100/cmdline", O_RDONLY)     = 3fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0read(3, "", 1024)                       = 0close(3)                                = 0open("/proc/104/stat", O_RDONLY)        = 3fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0read(3, "104 (ipv6_addrconf) I 2 0 0 0 -1"..., 1024) = 161close(3)                                = 0open("/proc/113/stat", O_RDONLY)        = 3fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0read(3, "113 (kstrp) I 2 0 0 0 -1 6923888"..., 1024) = 153close(3)                                = 0open("/proc/137/stat", O_RDONLY)        = 3fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0read(3, "137 (charger_manager) I 2 0 0 0 "..., 1024) = 163close(3)                                = 0open("/proc/137/cmdline", O_RDONLY)     = 3fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0read(3, "", 1024)                       = 0

打印结果很多,我只提取了部分,可以看到的是,killall会去proc文件系统(proc文件系统可以参考《Linux中不可错过的信息宝库》)下查找各个进程id下的stat文件和cmdline,stat文件是怎样的呢?我们随便找一个看看:

$ cat /proc/16131/stat 16131 (hello) S 6335 16131 6335 34820 16131 1077936128 70 0 0 0 0 0 0 0 20 0 1 0 2465163 4321280 194 18446744073709551615 4194304 4196092 140734969955328 0 0 0 0 0 0 1 0 0 17 0 0 0 0 0 0 6295056 6295608 19099648 140734969962804 140734969962812 140734969962812 140734969966576 0

我们不要被这么多内容吓到了,可以明显看到的是,里面有hello啊。至此我们可以猜测,killall命令会去读取进程在proc文件系统中的stat文件里的名字。那么如果这么名字和你要杀死的进程对不上不就找不到了吗?

至此,想必你已经明白前面问题的原因了。

https://mp.weixin.qq.com/s/6roIBVFSJKxgLLFea6OATg