Java是跨平台的,大部分程序也都是在Linux服务器上运行的。可是不少朋友其实对服务器了解并很少,对相关知识也是只知其一;不知其二。不少概念可能知道,可是并不十分清楚,仅仅是基本运用。可能不少新手朋友脱离了IDE或者web容器,都不知道怎么在服务器上运行程序。java
举个简单的例子,相信不少朋友刚接触Linux的时候都遇到过这个问题。咱们经过终端链接上服务器,经过命令行或者脚本运行了一个程序,而后关闭了终端链接,可能程序进程就消失了。咱们也可能知道,在启动命令后面加&符号,能够进程在后台运行,关闭终端后,进程依然会消失,但若是经过shell脚本去运行,关闭终端链接后,程序可能不会消失。或者咱们又知道能够经过nohup命令让进程在后台运行,而且关闭链接后,程序不会消失,到底为何呢?linux
下面我会用比较通俗的语言进行讲解,若是有错误,欢迎指正。web
当咱们链接到服务器之后,运行的命令,启动的程序,设置的环境变量,都会挂在当前的链接中(非特殊设置或者特殊命令),当链接关闭时,全部东西都会消失。shell
进程的关闭,是经过信号进行传递的。咱们经过kill
命令发送不一样的信号,去关闭指定的进程, 当咱们关闭终端链接时,会向当前终端链接的下游进程发送SIGHUP
信号(就是kill -1
),触发进程关闭动做。tomcat
咱们能够经过ps -fe|grep XXX
查询进程信息。服务器
[work ~]$ ps -fe|grep Test work 31133 30981 0 20:09 pts/4 00:00:00 java Test work 31277 23065 0 20:09 pts/1 00:00:00 grep --color Test
前三个分别对应 uid / pid(进程id) / ppid(父进程id),ppid其实就是当前终端链接的进程id。若是kill -9 ppid
,当前终端链接就断了。ui
有时候咱们执行一个命令,程序会在一直在运行,咱们能够经过ctrl+c
,发送的SIGINT
信号(就是kill -2
),中断程序。也能够经过ctrl+z
,发送SIGTSTP
信号,挂起进程,经过jobs
命令查看,经过fg
命令调起。.net
在linux中,经过命令行方式运行,属于交互模式。经过脚本方式运行属于非交互模式。 在非交互模式下,shell会对后台进程设置SIGINT信号忽略。命令行
因此咱们采用交互模式,也就是命令行方式运行java xxx &
,后台运行一个进程(在当前的终端链接下后台运行),关闭终端链接时,进程会关闭。而经过shell脚本的方式,执行java xxx &
命令,关闭链接时,java进程会把父进程id,切换挂在到init进程下(父进程id为1),也就是真正的后台运行了。code
nohup
命令会忽略SIGHUP信号,所以经过nohup java xxx &
的方式运行,不论采用交互模式或者非交互模式运行,在终端链接关闭时,都会挂到init进程下。
《Linux 技巧:让进程在后台可靠运行的几种方法》文中提到了三种后台运行的命令 nohup
/setsid
/(xxx &)
,后两个命令能够直接把进程挂在init进程下,也能够经过disown
命令把进程设置忽略SIGHUP
信号
在Linux中,经过信号,关闭进程,经过忽略信号,并把进程挂载到init进程下,保证进程能够后台运行。
本篇大部分结论也是参考《Tomcat进程意外退出的问题分析》一文
在上篇博文《Java消息队列任务的平滑关闭》 提到了Java对信号的监听,不知道的同窗能够看一下
ps:若是你们有感兴趣的技术点,能够私信我,欢迎关注