kill 命令很容易让人产生误解,以为它仅仅就是用来杀死进程的。我们来看一下 man page 对它的解释:kill - send a signal to a process.

从官方的解释不难看出, kill 是向进程发送信号的命令。当然我们可以向进程发送一个终止运行的信号,此时的 kill 命令才是名至实归。事实上如果我们不给 kill 命令传递信号参数,它默认传递终止进程运行的信号给进程!这是 kill 命令最主要的用法,也是本文要介绍的内容。

一般情况下,终止一个前台进程使用 Ctrl + C 就可以了。对于一个后台进程就须用 kill 命令来终止。我们会先使用 ps/pidof/pstree/top 等命令获得进程的 PID ,然后使用 kill 命令来杀掉该进程。

命令格式

1
kill [参数] [进程号]

命令功能

发送指定的信号到相应进程。

命令参数

  • -l 列出信号名称,不加信号的编号,则列出全部的信号名称
  • -a 当处理当前进程时,不限制命令名和进程号的对应关系
  • -p 指定 kill 命令只打印相关进程的进程号,而不发送任何信号
  • -s 指定发送信号
  • -u 指定用户

注意:

  1. 信号参数是可选的,默认值为 15TERM 信号应该先于 KILL 信号处理。因为一些进程可能会在 TERM 信号上定义一些清理工作。如果 TERM 信号处理后,程序没有退出,这时候再处理 KILL 信号。需要注意的是 KILL 信号是不可捕获的。所以使用 KILL 信号的时候,程序是没有机会进行清理工作的。

  2. kill 可以带有进程ID号作为参数。当用 kill 向这些进程发送信号时,必须是这些进程的主人。如果试图撤销一个没有权限撤销的进程或撤销一个不存在的进程,就会得到一个错误信息。

  3. 可以向多个进程发信号或终止它们。

  4. kill 成功地发送了信号后,shell会在屏幕上显示出进程的终止信息。有时这个信息不会马上显示,只有当按下 Enter 键使shell的命令提示符再次出现时,才会显示出来。

  5. 应注意,信号使进程强行终止,这常会带来一些副作用,如数据丢失或者终端无法恢复到正常状态。发送信号时必须小心,只有在万不得已时,才用 kill 信号( 9 ),因为进程不能首先捕获它。要撤销所有的后台作业,可以输入 kill 0 。因为有些在后台运行的命令会启动多个进程,跟踪并找到所有要杀掉的进程的PID是件很麻烦的事。这时,使用 kill 0 来终止所有由当前shell启动的进程,是个有效的方法。

使用实例

列出所有信号名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@localhost test6]# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

说明:

可以看到,一共有64个信号。其中,前32个信号属于Unix经典信号(即所有类Unix操作系统都提供的信号);后32个信号属于实时信号(用户实时自定义信号),即与特定的硬件驱动相匹配的信号。常用的是前32个信号,而后32个信号做底层驱动开发时能用到。

但这些信号中只有第 9 种信号(SIGKILL)才可以无条件的终止进程,其他信号进程都有权利忽略。并且这么多的信号中常用的也不多,下面我们解释几个常用信号的含义。

代号 名称 内容
1 SIGHUP 启动被终止的程序,可让该进程重新读取自己的配置文件,类似重新启动。
2 SIGINT 相当于用键盘输入 [ctrl]-c 来中断一个程序的进行。
9 SIGKILL 代表强制中断一个程序的进行,如果该程序进行到一半,那么尚未完成的部分可能会有“半产品”产生,类似 vim会有 .filename.swp 保留下来。
15 SIGTERM 以正常的方式来终止该程序。由于是正常的终止,所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时,输入这个 signal 也是没有用的。
18 SIGCONT 继续信号(对应19号暂停信号)
19 SIGSTOP 相当于用键盘输入 [ctrl]-z 来暂停一个程序的进行。

得到指定信号的数值

1
2
3
4
5
[root@localhost test6]# kill -l KILL
9[root@localhost test6]# kill -l SIGKILL
9[root@localhost test6]# kill -l TERM
15[root@localhost test6]# kill -l SIGTERM
15[root@localhost test6]#

先用ps查找进程,然后用kill杀掉

1
2
3
4
5
6
[root@localhost test6]# ps -ef|grep vim 
root      3268  2884  0 16:21 pts/1    00:00:00 vim install.log
root      3370  2822  0 16:21 pts/0    00:00:00 grep vim
[root@localhost test6]# kill 3268 
[root@localhost test6]# kill 3268 
-bash: kill: (3268) - 没有那个进程

彻底杀死进程

1
2
3
4
5
6
[root@localhost test6]# ps -ef|grep vim 
root      3268  2884  0 16:21 pts/1    00:00:00 vim install.log
root      3370  2822  0 16:21 pts/0    00:00:00 grep vim
[root@localhost test6]# kill –9 3268 
[root@localhost test6]# kill 3268 
-bash: kill: (3268) - 没有那个进程

杀死指定用户所有进程

1
2
[root@localhost ~]# kill -9 $(ps -ef | grep peidalinux) 
[root@localhost ~]# kill -u peidalinux

init进程是不可杀的

命令:

1
kill -9 1

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]# ps -ef|grep init
root         1     0  0 Nov02 ?        00:00:00 init [3]
root     17563 17534  0 17:37 pts/1    00:00:00 grep init
[root@localhost ~]# kill -9 1
[root@localhost ~]# kill -HUP 1
[root@localhost ~]# ps -ef|grep init
root         1     0  0 Nov02 ?        00:00:00 init [3]
root     17565 17534  0 17:38 pts/1    00:00:00 grep init
[root@localhost ~]# kill -KILL 1
[root@localhost ~]# ps -ef|grep init
root         1     0  0 Nov02 ?        00:00:00 init [3] 
root     17567 17534  0 17:38 pts/1    00:00:00 grep init
[root@localhost ~]#

说明:

init 是Linux系统操作中不可缺少的程序之一。所谓的 init 进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序 init 的方式,完成引导进程。所以, init 始终是第一个进程(其进程编号始终为 1 )。 其它所有进程都是 init 进程的子孙。 init 进程是不可杀的!

References