前言
Linux系统下如何kill掉一个后台Java进程,相信童鞋们都知道如何操作。首先使用ps命令查找该Java进程的进程ID,然后使用kill命令进行杀掉。命令如下:
(1)ps查进程ID
[user@data2 ~]$ ps -ef | grep Test
user 20950 20809 0 21:30 pts/1 00:00:00 java -jar Test.jar
user 21030 20996 0 21:30 pts/2 00:00:00 grep Test
(2)kill杀进程
[user@data2 ~]$ kill -9 20950
再使用ps命令查该进程,发现进程Test.jar已经被杀掉。使用“kill -9 $pid”杀Java进程,干净利落。但该方法是不是结束Java后台进程的较好方法呢?
场景
思考下面的场景:
“开发一个Java后台程序,其功能是不停地扫描Linux系统下的某个ftp目录。如果有文件,就经过数据转换写入到数据库中;如果没有文件,就sleep一秒钟。ftp目录下的文件不断地上传,Java程序处理完一个文件,就将该文件移到备份目录下面。”
该场景涉及Java程序进行文件打开、文件读取、文件备份、数据库连接、数据库写入等操作。因为文件句柄和数据库连接在Linux系统中是有限的资源,所以文件和数据库操作完成,需要进行关闭。
如果用户直接使用“kill -9”杀掉一个后台正在读取文件并写入数据库的Java进程。那么有可能文件和数据库连接没有正确关闭,而且数据文件也没有标识是否处理完成,或处理到哪个位置。
应用
近日在处理分布式消息Kafka的消息读取的工作,同样面临着上述场景的问题。如果读取了一条消息,在处理该消息之前进程被用户强行杀掉。那么该条消息就丢失了,既不在消息队列,也不在数据库或本地文件中。所以需要让后台Java进程在被杀的时候得到通知,这样就能安排好进程的“后事”。
Java中要得到kill信号通知,需要继承自“SignalHandler”类。完整实现代码如下:
import sun.misc.Signal;
import sun.misc.SignalHandler;
publicclass Engine implements SignalHandler {
privateboolean beKilling =false;
publicstaticvoid main(String[] args){
Engine signalHandler =new Engine();
Signal.handle(new Signal("TERM"), signalHandler); // kill -15
Signal.handle(new Signal("INT"), signalHandler); // Ctrl+c
Signal.handle(new Signal("USR2"), signalHandler); // kill -12
String zookeeper ="host1:2181,host2:2181,host3:2181";
String groupId ="gp01";
String topic ="test";
KafkaConsumer kc =new KafkaConsumer(zookeeper, groupId, topic);
//对读到的每一条kafka消息做处理
while(!signalHandler.beKilling && kc.hasNext()){
byte[] data = kc.getNext();
//转为String类型
String res=new String(data);
//消息处理逻辑
ProcessData d =new ProcessData();
d.processingMessage(res);
}
System.out.println("bye!");
}
@Override
publicvoid handle(Signal arg0){
// TODO Auto-generated method stub
beKilling =true;
}
}
说明:
(1)需要引用sun.misc的两个类:Signal和SignalHandler;
(2)添加一个变量bKilling用于标识该进程是否正在被杀,如果是,则跳出循环不在接收Kafka消息;
(3)一般接收“kill -15”的信号。
在eclipse开发环境中,引用sun.misc会报找不到类问题,其实该包在rt.jar包中。需要配置一下IDE,忽略掉Signal相关的错误和警告,如下图所示:
如果尝试响应其他kill信号,运行程序时会报如下错误:
[user@data2 test]$ java -jar Test.jar
Exception in thread "main" java.lang.IllegalArgumentException: Signal already used by VM or OS: SIGKILL
at sun.misc.Signal.handle(Signal.java:166)
at TestSignal.main(TestSignal.java:12)
进程的启动与关闭
Java后台进程启动和关闭
启动:
[user@data2 test]$ nohup java -jar Test.jar &
查看日志:
[user@data2 test]$ more nohup.out
running ......
running ......
…
查看进程:
[user@data2 test]$ ps -ef | grep Test.jar
unicom 28005 27711 0 22:24 pts/0 00:00:00 java -jar Test.jar
unicom 28062 27711 0 22:24 pts/0 00:00:00 grep Test.jar
关闭进程:
[user@data2 test]$ kill -15 28005
查看日志:
[user@data2 test]$ more nohup.out
running ......
…
running ......
TERM is recevied.
running ......
[1]+ Done nohup java -jar Test.jar
附录
在以下场景中需要使用SignalHandler来响应kill信号:
(1)文件操作;
(2)数据库操作;
(3)网络连接;
(4)循环处理的消息、数据记录等。
来源:CU技术社区
End
全国大学生科技创新大赛征稿函
征稿内容
机械设计等设计作品,通信作品、工程作品、机电作品、电子作品、科技作品等,可以是与之相关的论文,也可以是作品说明,只要是设计、通信、工程、机电、电子、科技等相关都可以。
评选方式
组委会本着“公开、公正、公平”的原则进行评审,奖项为一、二、三等奖,凡获奖作品均颁发荣誉证书。
1、由专家组成评审小组,对参赛作品进行评审。
2、部分优秀作品将在网站上宣传和表彰。
组别设置
本比赛下设组别与作品类别相同,如机械设计作品,则组别为机械设计组;通信作品,则组别为通信组,以此设置。
稿件发送
参赛作品以电子文档形式发送,邮件发送至:zgdxskjcxds@sina.com。主题为“大学生科技创新大赛+作品+作者姓名”。