前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux系统下如何优雅地关闭Java进程?

Linux系统下如何优雅地关闭Java进程?

作者头像
用户6543014
发布2019-10-25 19:17:38
5.4K0
发布2019-10-25 19:17:38
举报
文章被收录于专栏:CU技术社区

前言

Linux系统下如何kill掉一个后台Java进程,相信童鞋们都知道如何操作。首先使用ps命令查找该Java进程的进程ID,然后使用kill命令进行杀掉。命令如下:

(1)ps查进程ID[user@data2 ~]$ ps -ef | grep Testuser 20950 20809 0 21:30 pts/1 00:00:00 java -jar Test.jaruser 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.jarException 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.outrunning ......running ......…

查看进程:

[user@data2 test]$ ps -ef | grep Test.jarunicom 28005 27711 0 22:24 pts/0 00:00:00 java -jar Test.jarunicom 28062 27711 0 22:24 pts/0 00:00:00 grep Test.jar

关闭进程:

[user@data2 test]$ kill -15 28005

查看日志:

[user@data2 test]$ more nohup.outrunning ......…running ......TERM is recevied.running ......[1]+ Done nohup java -jar Test.jar

附录

在以下场景中需要使用SignalHandler来响应kill信号:

(1)文件操作;

(2)数据库操作;

(3)网络连接;

(4)循环处理的消息、数据记录等。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SACC开源架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档