這兩天在搭建VNC服務(wù)的時(shí)候此迅,遇到一個(gè)簡單的問題汽畴,卻困擾了我有一會(huì):網(wǎng)上的教程大部分是修改.service文件旧巾,然后啟動(dòng)服務(wù),但是我發(fā)現(xiàn)使用vncserver這個(gè)命令也可以達(dá)到同樣的目的忍些,這兩者之間有什么區(qū)別呢鲁猩?查了一些資料,簡單的做一個(gè)總結(jié)罢坝。
工作管理
一般情況下绳匀,我們可能會(huì)在命令行下這樣啟動(dòng)一個(gè)程序,以新做的版本管理系統(tǒng)為例:
java -jar VersionManager.jar
現(xiàn)在炸客,內(nèi)網(wǎng)中的其他機(jī)器可以通過80端口訪問本機(jī)提供的web服務(wù)了疾棵。一切都很正常。
注意到一個(gè)問題痹仙,新啟動(dòng)的程序獨(dú)占了命令行窗口是尔,并隨時(shí)打印一些程序運(yùn)行期間的log出來。
如果想在同一個(gè)命令行窗口再執(zhí)行其他命令开仰,那么需要Ctrl+c停止這個(gè)web服務(wù)才可以拟枚。
這個(gè)時(shí)候的web服務(wù)稱為前臺任務(wù)
,一旦我們退出這個(gè)命令行窗口众弓,該服務(wù)也隨之關(guān)閉恩溅,無法訪問。
如何將其變成一個(gè)后臺執(zhí)行的任務(wù)谓娃,從而不影響命令行再執(zhí)行其他命令呢脚乡?
java -jar VersionManager.jar &
只要在命令的尾部加上符號&,啟動(dòng)的進(jìn)程就會(huì)成為"后臺任務(wù)"滨达。"后臺任務(wù)"有兩個(gè)特點(diǎn):
繼承當(dāng)前 session (對話)的標(biāo)準(zhǔn)輸出(stdout)和標(biāo)準(zhǔn)錯(cuò)誤(stderr)奶稠。因此,后臺任務(wù)的所有輸出依然會(huì)同步地在命令行下顯示捡遍。
不再繼承當(dāng)前 session 的標(biāo)準(zhǔn)輸入(stdin)锌订。你無法向這個(gè)任務(wù)輸入指令了。如果它試圖讀取標(biāo)準(zhǔn)輸入画株,就會(huì)暫停執(zhí)行(halt)辆飘。
所以,我們以上述方式啟動(dòng)web服務(wù)谓传,他的運(yùn)行日志依然會(huì)打印在屏幕上面蜈项。但是與前臺任務(wù)的一個(gè)區(qū)別就是,現(xiàn)在可以在命令行執(zhí)行其他命令了良拼,所有的輸出都會(huì)混雜在一起打印在屏幕上战得。
有沒有辦法解決這種問題呢?那就是重定向:
java -jar VersionManager.jar >info.log 2>&1 &
上述命令把web服務(wù)輸出的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤信息都重定向到了info.log這個(gè)文件庸推,屏幕上不會(huì)再有任何的信息被打印出來了常侦。你也可以像之前那樣查看web服務(wù)的輸出信息:
tail -f info.log
此時(shí)浇冰,web服務(wù)的輸出又動(dòng)態(tài)的在屏幕上打印出來了。
如果要讓正在運(yùn)行的"前臺任務(wù)"變?yōu)?后臺任務(wù)"聋亡,可以先按ctrl + z肘习,然后執(zhí)行bg命令。(讓最近一個(gè)暫停的"后臺任務(wù)"繼續(xù)執(zhí)行)
如何查看當(dāng)前session有哪些后臺任務(wù)在運(yùn)行呢坡倔?
$ jobs -l //打印pid
[1]- 17000 運(yùn)行中 nohup java -jar VersionManager.jar > logs/info.log 2>&1 &
[2]+ 22738 停止 vim cron.log
將指定的后臺任務(wù)變成前臺執(zhí)行:
fg 2 //繼續(xù)編輯cron.log
最后做一個(gè)小結(jié):
查看后臺任務(wù):jobs -l
將后臺任務(wù)取回前臺:fg number //number為任務(wù)號
暫停前臺任務(wù)漂佩,并將任務(wù)放到后臺:ctrl + z
暫停的后臺任務(wù)繼續(xù)執(zhí)行:bg number //number為任務(wù)號
結(jié)束前臺任務(wù):ctrl + c
結(jié)束后臺任務(wù):kill pid //pid可以通過jobs -l進(jìn)行查看
脫機(jī)管理
通過上面的內(nèi)容,我們了解到如何將一個(gè)任務(wù)放在后臺執(zhí)行罪塔。后臺任務(wù)都是基于當(dāng)前session的投蝉,如果我們退出了當(dāng)前的session(關(guān)閉了命令行窗口或執(zhí)行exit),后臺任務(wù)還會(huì)執(zhí)行嗎征堪?
想起了之前有個(gè)現(xiàn)場的技術(shù)支持人員打電話跟我反映瘩缆,一個(gè)rest服務(wù)總是無規(guī)律的宕掉。剛開始我也想不通佃蚜,后來才想到是上面提到的原因...
看一下session退出的時(shí)候發(fā)生了什么:
用戶準(zhǔn)備退出 session
系統(tǒng)向該 session 發(fā)出SIGHUP信號
session 將SIGHUP信號發(fā)給所有子進(jìn)程
子進(jìn)程收到SIGHUP信號后庸娱,自動(dòng)退出
上面的流程可以解釋,隨著session退出谐算,前臺任務(wù)也會(huì)結(jié)束熟尉。那么后臺任務(wù)是否也會(huì)收到SIGHUP信號后退出呢?
這由 Shell 的huponexit參數(shù)決定的洲脂。
shopt | grep huponexit
執(zhí)行上面的命令斤儿,就會(huì)看到huponexit參數(shù)的值。如果顯示off
腮考,表示session 退出的時(shí)候雇毫,不會(huì)把SIGHUP信號發(fā)給"后臺任務(wù)",從而"后臺任務(wù)"不會(huì)隨著 session 一起退出踩蔚。
但是,為了確保我們的web服務(wù)變成一個(gè)可靠的守護(hù)進(jìn)程枚粘,我們應(yīng)該顯式的指出 session 退出的時(shí)候馅闽,不把SIGHUP信號發(fā)給"后臺任務(wù)":
nohup
nohup java -jar VersionManager.jar &
nohup
對java -jar VersionManager.jar
命令做了幾件事:
阻止SIGHUP信號發(fā)到這個(gè)進(jìn)程。
關(guān)閉標(biāo)準(zhǔn)輸入馍迄。該進(jìn)程不再能夠接收任何輸入福也,即使運(yùn)行在前臺。
重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤到文件nohup.out攀圈。
一般情況下暴凑,我們會(huì)重定向web服務(wù)的輸出:
nohup java -jar VersionManager.jar >info.log 2>&1 &
至此,我們的web服務(wù)已經(jīng)變成了一個(gè)可靠的守護(hù)進(jìn)程赘来。
tmux
還有一種方法现喳,那就是使用tmux凯傲。tmux可以在當(dāng)前session里新建一個(gè)session。當(dāng)前的session退出不會(huì)影響到新建的session嗦篱。重新登錄之后還可以連上之前建立的session冰单。
// 新建 session
$ tmux new -s session_name
// 切換到指定 session
$ tmux attach -t session_name
// 列出所有 session
$ tmux list-sessions
// 退出當(dāng)前 session,返回前一個(gè) session
$ tmux detach
// 殺死指定 session
$ tmux kill-session -t session-name
systemd服務(wù)
systemd 是 Linux 下的一款系統(tǒng)和服務(wù)管理器灸促。Systemd 并不是一個(gè)命令诫欠,而是一組命令,涉及到系統(tǒng)管理的方方面面浴栽。
在centos7中荒叼,我們也許會(huì)使用systemd來管理我們的一些程序,比如ssh:
// 啟動(dòng)ssh服務(wù)
systemctl start sshd.service
// 設(shè)置ssh服務(wù)開機(jī)啟動(dòng)
systemctl enable sshd.service
...
我們也可以通過systemd來管理我們的守護(hù)進(jìn)程典鸡,成為真正意義上的系統(tǒng)服務(wù)甩挫。
關(guān)于systemd的使用不再贅述,參考Systemd (簡體中文)