一、前言
相信大家在使用類unix系統(linux、macos)的時候,肯定有一些後臺運行程序的需求,如啓動tomcat,啓動各種各樣的服務時,都有一個需求,那就是想即使我們當前這個終端(terminal)關閉後,仍然可以保持程序的繼續運行。
二、正文
&,子進程式的後臺運行,不靠譜
其實我們都知道有個命令 &,這個的意思是後臺運行,雖然我們使用這個&之後,程序是進入後臺運行了,可以不受我們crtl+c的這種強制退出命令的干擾一直執行,但是如果我們退出當前的終端,也會導致整個程序的退出。
比如我們當前測試使用ping命令。
ping www.baidu.com &
在後面加上&後,ping進入後臺執行,但是他的輸出依舊爲當前終端,因此我們會看到ping命令的輸出,此時ctrl+c無法終端進程,因爲ping已經進入了當前系統的後臺。此時我們可以通過 ps -ef |grep ping 。查看ping的進程號30524,然後kill掉它。
但是其實由於類unix系統的特性,由當前進程啓動的進程均默認爲當前線程的子進程,而且在父進程退出(exit)之後,其下的所有相關子進程均會接收到信號退出,因此我們剛纔使用 ping www.baidu.com& 命令即使進入了後臺運行,但在我們當前操作的終端退出後,ping進程也會被kill掉,可以嘗試一下。
因此光是&保持後臺運行還不行,因此需要讓我們衍生出來的子進程忽略掉父進程的退出信號 HUP(hangup),這裏就牽扯到了另外一個東西nohup。
nohup+&,後臺運行忽略hup信號
nohup的意思就是我們當前啓用的這個進程,會忽略由父進程被銷燬帶來的hup信號而避免退出。讓我們先來看一下 nohup 的幫助信息:
[root@ls ~]# nohup --help
Usage: nohup COMMAND [ARG]...
or: nohup OPTION
Run COMMAND, ignoring hangup signals.
--help display this help and exit
--version output version information and exit
If standard input is a terminal, redirect it from /dev/null.
If standard output is a terminal, append output to 'nohup.out' if possible,
'$HOME/nohup.out' otherwise.
If standard error is a terminal, redirect it to standard output.
To save output to FILE, use 'nohup COMMAND > FILE'
可見,nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標準輸出和標準錯誤缺省會被重定向到 nohup.out 文件中。一般我們可在結尾加上"&"來將命令同時放入後臺運行,也可用">filename 2>&1"
來更改缺省的重定向文件名。即 nohup ping www.baidu.com &,這個命令會缺省的在當前目錄下將ping進程的輸出重定向到nohup.out 中。
當然,也可以指定輸出文件
nohup ping www.baidu.com >ping.log &
setid,將進程變爲非終端子進程
上面的nohup解決方案是將當前終端啓動的子進程完全忽略父進程的hup信號,完成後臺運行且不受干擾。但是如果我們換個思路呢,將當前子進程變爲非終端啓動的子進程,那麼終端退出之後,這個子進程也就不會收到hup信號了。
setsid 就能幫助我們做到這一點,如下
setsid ping www.baidu.com
查看進程信息之後如下所示:,當前啓動的ping,父進程號爲1,1號進程爲linux的系統內核進程,因此當前進程便不會受到其他進程的影響。
三、結語
在這篇博客中,我們介紹了兩種在類unix系統中將進程後臺運行的辦法,及nouhp+&、setsid,均能有效執行。
其實不僅僅是後臺運行進程的需求,我們在創建一個守護進程時也需要對守護進程做出這個後臺運行操作。
筆者在使用jenkins部署腳本時就忽略了父子進程間的關係問題,每次啓動完腳本後就忽略了腳本父進程已經結束,因此子進程也無法正常運行,使用nohup解決。