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:若是你們有感興趣的技術點,能夠私信我,歡迎關注