△Hollis, 一个对Coding有着独特追求的人△
相信很多程序员对于Linux系统都不陌生,即使自己的日常开发机器不是Linux,那么线上服务器也大部分都是的,所以,掌握常用的Linux命令也是程序员必备的技能。
但是,怕就怕很多人对于部分命令只是一知半解,使用不当就能导致线上故障。
前段时间,我们的线上应用报警,频繁FGC,需要紧急处理问题,于是有同事去线上重启机器(正常程序应该是先采集堆dump,然后再重启,方便排查是否存在内存泄露等问题)。
但是在重启过程中,同事发现正常的重启命令应用无反应,然后尝试使用kill命令"杀"掉Java进程,但是仍然无效。于是他私自决定使用 "kill -9"结束了进程的生命。
虽然应用进程被干掉了,但是随之而来带来了很多问题,首先是上游系统突然发生大量报警,对应开发找过来说调用我们的RPC服务无响应,频繁超时。
后来,我们又发现系统中存在部分脏数据,有些在同一个事务中需要完整更新的数据,只更新了一半…
为什么正常的kill无法"杀掉"进程,而kill -9
就可以?为什么kill -9
会引发这一连串连锁反应?正常的kill执行时,JVM会如何处理的呢?
要搞清楚这些问题,我们要先从kill命令说起。
我们都知道,想要在Linux中终止一个进程有两种方式,如果是前台进程可以使用Ctrl+C键进行终止;如果是后台进程,那么需要使用kill命令来终止。(其实Ctrl+C也是kill命令)
kill命令的格式是:
kill[参数][进程号]
如:
kill 21121
kill -9 21121
其中[参数]是可选的,进程号可以通过jps/ps/pidof/pstree/top等工具获取。
kill的命令参数有以下几种:
-l 信号,若果不加信号的编号参数,则使用“-l”参数会列出全部的信号名称
-a 当处理当前进程时,不限制命令名和进程号的对应关系
-p 指定kill 命令只打印相关进程的进程号,而不发送任何信号
-s 指定发送信号
-u 指定用户
通常情况下,我们使用的-l
(信号)的时候比较多,如我们前文提到的kill -9
中的9
就是信号。
信号如果没有指定的话,默认会发出终止信号(15)。常用的信号如下:
HUP 1 终端断线
INT 2 中断(同 Ctrl + C)
QUIT 3 退出(同 Ctrl + \)
TERM 15 终止
KILL 9 强制终止
CONT 18 继续(与STOP相反, fg/bg命令)
STOP 19 暂停(同 Ctrl + Z)
比较常用的就是强制终止信号:9
和终止信号:15
,另外,中断信号:2
其实就是我们前文提到的Ctrl + C结束前台进程。
那么,kill -9
和 kill -15
到底有什么区别呢?该如何选择呢?
kill命令默认的信号就是15,首先来说一下这个默认的kill -15
信号。
当使用kill -15
时,系统会发送一个SIGTERM的信号给对应的程序。当程序接收到该信号后,具体要如何处理是自己可以决定的。
这时候,应用程序可以选择:
kill -15
信号只是通知对应的进程要进行"安全、干净的退出",程序接到信号之后,退出前一般会进行一些"准备工作",如资源释放、临时文件清理等等,如果准备工作做完了,再进行程序的终止。kill -15
相比,kill -9
就相对强硬一点,系统会发出SIGKILL信号,他要求接收到该信号的程序应该立即结束运行,不能被阻塞或者忽略。正常关闭:当最后一个非守护线程结束或者调用了System.exit或者通过其他特定平台的方法关闭(接收到SIGINT(2)、SIGTERM(15)信号等) 强制关闭:通过调用Runtime.halt方法或者是在操作系统中强制kill(接收到SIGKILL(9)信号) 异常关闭:运行中遇到RuntimeException异常等。
kill -15
信号通知的时候,是可以做一些清理动作的,比如删除临时文件等。package com.hollis;
public class ShutdownHookTest {
public static void main(String[] args) {
boolean flag = true;
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("hook execute...");
}));
while (flag) {
// app is runing
}
System.out.println("main thread execute end...");
}
}
➜ jps
6520 ShutdownHookTest
6521 Jps
➜ kill 6520
hook execute...
Process finished with exit code 143 (interrupted by signal 15: SIGTERM)
interrupted by signal 15: SIGTERM
kill -9
:➜ kill -9 6520
Process finished with exit code 137 (interrupted by signal 9: SIGKILL)
interrupted by signal 9: SIGKILL
kill -15
。kill -15
执行时,系统向对应的程序发送SIGTERM(15)信号,该信号是可以被执行、阻塞和忽略的,所以应用程序接收到信号后,可以做一些准备工作,再进行程序终止。kill -15
无法终止程序,因为他可能被忽略,这时候可以使用kill -9
,系统会发出SIGKILL(9)信号,该信号不允许忽略和阻塞,所以应用程序会立即终止。kill -9
命令,尤其是那些web应用、提供RPC服务、执行定时任务、包含长事务等应用中,因为kill -9
没给spring容器、tomcat服务器、dubbo服务、流程引擎、状态机等足够的时间进行收尾。感谢大家一直以来的陪伴与支持
今天给大家赠送10本书
由北京大学出版社赞助
本次送书不需要评论,也不需要转发
采用最公平的抽奖方式。
关注公众号:程序员面试现场
公众号后台回复:送书
即可参与抽奖
往期推荐
我以为我是后浪!
面试官真是搞笑!让实现线程安全的单例,又不让使用synchronized!
if快还是switch快?解密switch背后的秘密
直面Java第314期:运行时常量池中常量的来源?
深入并发第013期:拓展synchronized——锁优化
如果你喜欢本文,
请长按二维码,关注 Hollis.
转发至朋友圈,是对我最大的支持。