最近用maven工程的形式打jar包写一个小型服务器,于是希望提供脚本的形式启动和关闭服务器。
网上浏览到一些文章,基本思路是:
1.在start.sh中启动Java程序,保存pid到文件server.pid
2.在shutdown.sh中使用 kill -9 pid 的形式杀死Java进程
问题是:kill -9 pid 会强制杀死进程,而我的需求是,在程序退出前,执行一些清理操作,比如将缓存存库。
下面来介绍如何实现“优雅”地关闭Java程序。
不难理解,我们要关闭的Java程序,就是操作系统中的一个进程。在杀死进程前,我们要执行一些操作,所以涉及到进程通信的问题。
信号是进程通信的一种手段,可以理解为事件机制,当进程接受到一个特定类型的信号,就会执行相应的逻辑处理。
Linux的信号类型如下:
通过相应的信号,通知相应的Java程序进程(一个jvm实例),从而Java程序可以在程序终止前执行一些逻辑处理。
如何使用信号:
Linux环境下 kill -12 pid 会发送SIGUSR2类型的信号到pid对应的进程
为了响应信号,我们要用到两个类:
sun.misc.Signal:代表信号
sun.misc.SignalHandler:响应信号的接口
这两个类来自sun.misc包,这个包下的类是设计被jdk类库使用的,所以代码提示不会出现这两个类,需要手动import,并且编译器会发出警告。
示例代码:
在上面的handle方法中,我执行了exit()方法,是为了触发ShowdownHook线程。
jdk提供了一个钩子方法,从而在程序终止时,在一个独立的线程中执行终止逻辑。注册ShowdownHook方式如下:
然后当执行System.exit(),或其他非强制方式去关闭Java程序时,该方法会被执行。
通过maven打jar包,我的jar包名称是:
测试过程:
1.后台模式启动Java程序,重定向输出到test.log
可以看到进程启动成功,pid为45393
2.kill -12 45393 ,和Java进程进行信号通信,从而触发SignalHandler执行
可以看到ShutdownHook线程中代码被执行,程序优雅终止完成!
当然,还有最后一步,写shell脚本,完成程序启动和优雅关闭,关于这点,可以看下面的参考文章,结合上述优雅终止的方式,写出相应的shell脚本。
signal:
https://blog.csdn.net/u011001084/article/details/73480432
https://blog.csdn.net/carlislelee/article/details/52688693
maven:
https://blog.csdn.net/xiao__gui/article/details/47341385
shell脚本:
https://blog.csdn.net/e_wsq/article/details/51767165
https://blog.csdn.net/clerk0324/article/details/50593882