15.LINUX命令kill

发布时间 2023-08-22 18:28:40作者: CodeMagicianT

15.LINUX命令kill

1.kill命令简介

在Linux统中,kill命令用于向运行中的进程发送信号,默认发送的信号是终止信号,会请求进程退出。kill(杀)可能会引起误解,实际上发送的信号可能与杀死进程无关。

我们最常使用到的kill命令为:

kill PID
kill -9 PID

前者为请求目标进程退出,后者为强制杀死目标进程。

1.1kill PID

kill命令默认发送的信号是SIGTERM。该信号会被目标进程捕获,在收到这个信号以后目标进程可以做一些有用的操作(如保存数据),然后退出。然而,许多进程并没有专门实现处理此信号的程序,此时会调用默认的信号处理函数。而在某些情况下,有特殊处理程序的进程也会出错,无法正确处理信号。总之,SIGTERM信号不能确保目标进程能够退出。

SIGTERM信号的编号通常为15,可通过以下四种方式发送SIGTERM信号:

kill PID
kill -s TERM PID
kill -TERM PID
kill -15 PID

1.2 kill -9 PID

此时发送的是SIGKILL信号。正如前文所述,SIGTERM信号不一定能够“杀死”目标进程,在这种情况下,我们就会释放大杀器,SKGKILL信号。SIGKILL信号不会被进程所“截获”,它只能由主机系统内核处理,由其负责提供可靠的控制进程执行的方法,SIGKILL会杀死进程。

SIGKILL信号的编号通常为9,可通过三种方式发送SIGKILL信号:

kill -s KILL PID
kill -KILL PID
kill -9 PID

1.3其他kill信号

kill命令可以发送的信号还有很多,其它有用的信号包括HUP、TRAP、INT、SEGV及ALRM等。

HUP发送SIGHUP信号,SIGHUP信号的意思为挂起。在规范上,进程应当在收到这个信号时重新加载配置,相当于重启。但在实际使用中,通常只有守护进程会按照规范实施,而普通进程则是执行退出。

INT发送SIGINT信号,意为中断,在终端中,只需按下CTRL+C便可以产生SIGINT信号。

在终端中,CTRL+Z通常映射至SIGTSTP,CTRL+\(反斜杠)映射至SIGQUIT,这可强制程序进行核心转储。

2.kill能确保杀死进程吗?

答案是否定的,某些情况下即使kill -9也无法杀死进程。

2.1用户授权

UNIX提供了安全机制,以防止未授权用户杀死其他进程。实际上,若进程欲向另一个进程发送信号,发送信号的进程的所有者必须与接收信号的进程的所有者相同,或者发送信号的进程的所有者是超级用户root。

例如,假设当前终端的用户是dancen,则无法kill掉用户nginx启动的进程。

2.2超级进程

即使root用户也无法向PID为1的进程发送信号。内核初始化的最后一步就是启动init进程。这个进程是系统的第一个进程,PID为1,又叫超级进程,也叫根进程。它负责产生其他所有用户进程。所有的进程都会被挂在这个进程下,如果这个进程退出了,那么所有的进程都被kill。如果一个子进程的父进程退了,那么这个子进程会被挂到PID 1下面,即PPID为1。

2.3内核态进程

当一个进程执行系统调用而陷入内核代码中执行时,该进程由用户态转为内核态,处于内核态的进程将忽略所有信号处理。如果进程在执行系统调用时无限期地阻塞,则可能无法终止该进程。

2.4僵尸进程

进程停止后,该进程就会从进程列表中移除。但是,有时候有些进程即使执行完了也依然留在进程列表中。这些完成了生命周期但却依然留在进程列表中的进程,我们称之为 “僵尸进程”。

a. 僵尸进程的产生

一个进程可能会产生很多子进程。这些子进程执行完毕后会发送一个Exit信号然后死掉。这个Exit信号需要被父进程所读取。父进程随后调用wait命令来读取子进程的退出状态,并将子进程从进程列表中移除。但若父进程未能读取到子进程的Exit信号,则这个子进程不会从进程列表中删掉。

b. 找出僵尸进程

ps aux | grep Z

c. kill僵尸进程

我们可以分别通过SIGTERM信号、SIGKILL信号、SIGHUP信号来尝试kill僵尸进程。

kill PID
kill -9 PID
kill -HUP PID

如果僵尸进程没能kill掉,则可查看僵尸进程的PPID,找到父进程,令其回收子进程;如果无效,则可直接kill掉僵尸进程的父进程,父进程死后,僵尸进程成为”孤儿进程”,过继给1号进程init,由init负责清理僵尸进程。

方法一,传递信号给父进程,命令其回收子进程的资源

kill -CHLD PPID

方法二,直接kill父进程,将此进程变成孤儿进程,交给init进程管理,由init进程回收此进程的资源

kill -9 PPID

2.5自我保护的进程

最后这一种情况是我在阿里云的服务器上遇到的。

我在执行硬盘扩展时,需要将硬盘卸载,但在执行umount命令时,提示设备忙。

a. 找出正在使用设备的进

# fuser -mv /mnt/volume1/
                     USER        PID ACCESS COMMAND
/mnt/volume1:        root     kernel mount /mnt/volume1
                     root      10516 f.... AliYunDun

结果显示名为AliYunDun的进程占用了设备。

b. kill AliYunDun进程1

# kill 10516
bash: kill: (10516) - Operation not permitted
 
# kill -9 10516
bash: kill: (10516) - Operation not permitted
 
# sudo kill -9 10516
kill: sending signal to 10516 failed: Operation not permitted

AliYunDun是阿里云安全中心的客户端代理,为了防止被恶意kill,具有自我保护功能,我在kill该进程时,提示没有权限,并且收到了阿里云的告警:

c. kill AliYunDun进程2

暂时不知道AliYunDun自我保护功能的实现原理,但该进程可以通过 HUP信号kill掉。

kill -HUP 1051

d. 补充资料

卸载阿里云安全中心Agent官方文档:

https://help.aliyun.com/document_detail/68616.htm?spm=a2c4g.11186623.2.7.2537646azwEGcG#concept-cwf-hzc-zdb

参考资料:

Linux中execl函数详解与日常应用(附图解与代码实现)