簡(jiǎn)介
在Linux服務(wù)器實(shí)際應(yīng)用中免都,經(jīng)常會(huì)有需要長(zhǎng)時(shí)間執(zhí)行的任務(wù)。這類任務(wù)若在前臺(tái)運(yùn)行绕娘,用戶無法進(jìn)行其他操作或者斷開與服務(wù)器的連接脓规,否則任務(wù)將被中止。此時(shí)適合使用守護(hù)進(jìn)程险领。為了使用守護(hù)進(jìn)程侨舆,需要了解Linux前臺(tái)绢陌、后臺(tái)挨下、守護(hù)進(jìn)程的概念與使用臭笆,本文將對(duì)此進(jìn)行講解。
創(chuàng)建守護(hù)進(jìn)程
- 終端(terminal)是計(jì)算機(jī)用于文本輸入與顯示的交互界面帜讲。
A text terminal, or often just terminal (sometimes text console) is a serial computer interface for text entry and display.
https://en.wikipedia.org/wiki/Computer_terminal#Text_terminals
- 前臺(tái)任務(wù)(foreground job)是獨(dú)占命令行窗口的任務(wù),只有運(yùn)行完了或者手動(dòng)中止該任務(wù),才能執(zhí)行其他命令在验。
- 后臺(tái)任務(wù)(background job),與前臺(tái)任務(wù)相對(duì)應(yīng)堵未,在多任務(wù)系統(tǒng)中腋舌,有一些任務(wù)在運(yùn)行的時(shí)候,并不需要與用戶交互渗蟹。它們通常在不打擾用戶其它工作的時(shí)候默默地執(zhí)行(此時(shí)可以輸入其他的命令)块饺。后臺(tái)任務(wù)繼承當(dāng)前session(對(duì)話,就是終端窗口)的標(biāo)準(zhǔn)輸出(stdout)和標(biāo)準(zhǔn)錯(cuò)誤(stderr)雌芽。因此授艰,后臺(tái)任務(wù)的所有輸出依然會(huì)同步地在命令行下顯示。不再繼承當(dāng)前session的標(biāo)準(zhǔn)輸入(stdin)世落。你無法向這個(gè)任務(wù)輸入指令了淮腾。如果它試圖讀取標(biāo)準(zhǔn)輸入,就會(huì)暫停執(zhí)行(halt)。
- 守護(hù)進(jìn)程(daemon)是指在UNIX或其他多任務(wù)操作系統(tǒng)中在后臺(tái)執(zhí)行的電腦程序谷朝,并不會(huì)接受電腦用戶的直接操控洲押。此類程序會(huì)被以進(jìn)程的形式初始化。守護(hù)進(jìn)程程序的名稱通常以字母“d”結(jié)尾:例如圆凰,syslogd就是指管理系統(tǒng)日志的守護(hù)進(jìn)程杈帐。用戶退出session之后,“后臺(tái)任務(wù)是否會(huì)繼續(xù)執(zhí)行”是判定這一任務(wù)是否為“守護(hù)進(jìn)程”的依據(jù)送朱。
可以看出娘荡,”后臺(tái)任務(wù)”與”前臺(tái)任務(wù)”的重要區(qū)別:是否繼承標(biāo)準(zhǔn)輸入。所以驶沼,執(zhí)行后臺(tái)任務(wù)的同時(shí)炮沐,用戶還可以輸入其他命令。
為了理解守護(hù)任務(wù)為何在結(jié)束session時(shí)也不退出回怜,需要先了解Linux下退出session時(shí)發(fā)生的操作大年。
Session退出時(shí),linux系統(tǒng)設(shè)計(jì)如下:
- 用戶準(zhǔn)備退出 session
- 系統(tǒng)向該 session 發(fā)出SIGHUP信號(hào)
- session 將SIGHUP信號(hào)發(fā)給所有子進(jìn)程
- 子進(jìn)程收到SIGHUP信號(hào)后玉雾,自動(dòng)退出
前臺(tái)任務(wù)會(huì)隨著session的退出而退出是因?yàn)樗盏搅?strong>SIGHUP信號(hào)翔试。
后臺(tái)任務(wù)是否會(huì)受到SIGNUP信號(hào),取決于shell的 huponexit 參數(shù)复旬】衙澹可以通過 $ shopt | grep huponexit 查看該參數(shù)的值。大多數(shù)Linux系統(tǒng)驹碍,這個(gè)參數(shù)默認(rèn)關(guān)閉(off)壁涎。因此,session退出的時(shí)候志秃,不會(huì)把SIGHUP信號(hào)發(fā)給”后臺(tái)任務(wù)”怔球,即此時(shí)的后臺(tái)任務(wù)是守護(hù)進(jìn)程,但這顯然不夠安全浮还。并不保險(xiǎn)竟坛,因?yàn)橛械南到y(tǒng)的huponexit參數(shù)可能是打開的(on)狀態(tài)。
更保險(xiǎn)的方法是使用disown命令钧舌。它可以將指定任務(wù)從”后臺(tái)任務(wù)”列表(jobs命令的返回結(jié)果)之中移除担汤。一個(gè)”后臺(tái)任務(wù)”只要不在這個(gè)列表之中,session 就肯定不會(huì)向它發(fā)出SIGHUP信號(hào)洼冻。
$ node server.js &
$ disown
執(zhí)行上面的命令以后崭歧,server.js
進(jìn)程就被移出了”后臺(tái)任務(wù)”列表。你可以執(zhí)行jobs
命令驗(yàn)證碘赖,輸出結(jié)果里面驾荣,不會(huì)有這個(gè)進(jìn)程。
但是普泡,這樣還存在問題播掷。因?yàn)?strong>”后臺(tái)任務(wù)”的標(biāo)準(zhǔn) I/O 繼承自當(dāng)前 session,disown
命令并沒有改變這一點(diǎn)撼班。一旦”后臺(tái)任務(wù)”讀寫標(biāo)準(zhǔn) I/O歧匈,就會(huì)發(fā)現(xiàn)它已經(jīng)不存在了,所以就報(bào)錯(cuò)終止執(zhí)行砰嘁。 為了解決這個(gè)問題件炉,需要對(duì)”后臺(tái)任務(wù)”的標(biāo)準(zhǔn) I/O 進(jìn)行重定向。
$ node server.js > stdout.txt 2> stderr.txt < /dev/null &$ disown
這樣基本上就沒有問題了矮湘。
注:
/dev/null
文件的作用
這是一個(gè)無底洞斟冕,任何東西都可以定向到這里,但是卻無法打開缅阳。
所以一般很大的stdou和stderr當(dāng)你不關(guān)心的時(shí)候可以利用stdout和stderr定向到這里
$ ./command.sh >/dev/null 2>&1
更簡(jiǎn)便地創(chuàng)建守護(hù)進(jìn)程: nohup 命令
$ nohup node server.js &
nohup命令對(duì)server.js進(jìn)程做了三件事磕蛇。
阻止SIGHUP信號(hào)發(fā)到這個(gè)進(jìn)程。
關(guān)閉標(biāo)準(zhǔn)輸入十办。該進(jìn)程不再能夠接收任何輸入秀撇,即使運(yùn)行在前臺(tái)。
重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤到文件nohup.out向族。
也就是說呵燕,nohup命令實(shí)際上將子進(jìn)程與它所在的 session 分離了。 注意件相,nohup命令不會(huì)自動(dòng)把進(jìn)程變?yōu)椤焙笈_(tái)任務(wù)”再扭,所以必須加上&符號(hào)
總結(jié)
守護(hù)進(jìn)程創(chuàng)建方法:
方法一:
$ node server.js > stdout.txt 2> stderr.txt < /dev/null &
$ disown
方法二:
$ node server.js > stdout.txt 2> stderr.txt < /dev/null
^z
$ bg
$ disown
方法三:
$ nohup node server.js &
命令總結(jié)
fg、bg适肠、jobs霍衫、&、nohup侯养、ctrl+z敦跌、ctrl+c 命令
一、&
加在一個(gè)命令的最后逛揩,可以把這個(gè)命令放到后臺(tái)執(zhí)行柠傍,如:
# 每10s在后臺(tái)執(zhí)行一次test.sh腳本
$ watch -n 10shtest.sh &
二、ctrl + z
可以將一個(gè)正在前臺(tái)執(zhí)行的命令放到后臺(tái)辩稽,并且處于暫停狀態(tài)惧笛。
CTRL+Z 和 CTRL+C的對(duì)比
CTRL+Z 和 CTRL+C 都是中斷命令,但是他們的作用卻不一樣.
CTRL+C 是強(qiáng)制中斷程序的執(zhí)行,而 CTRL+Z 的是將任務(wù)中斷,但是此任務(wù)并沒有結(jié)束,仍然在進(jìn)程中逞泄,只是維持掛起的狀態(tài)患整,用戶可以使用 fg/bg 操作繼續(xù)前臺(tái)或后臺(tái)的任務(wù)拜效。
三、jobs
查看當(dāng)前有多少在后臺(tái)運(yùn)行的進(jìn)程
jobs -l選項(xiàng)可顯示所有任務(wù)的PID各谚,jobs的狀態(tài)可以是running, stopped, Terminated紧憾。但是如果任務(wù)被終止了(kill),shell 從當(dāng)前的shell環(huán)境已知的列表中刪除任務(wù)的進(jìn)程標(biāo)識(shí)昌渤。
四赴穗、fg
將后臺(tái)中的命令調(diào)至前臺(tái)繼續(xù)運(yùn)行。如果后臺(tái)中有多個(gè)命令膀息,可以用fg %jobnumber
(jobnumber是命令編號(hào)般眉,不是進(jìn)程號(hào))將選中的命令調(diào)出。
五潜支、bg
將一個(gè)在后臺(tái)暫停的命令甸赃,變成在后臺(tái)繼續(xù)執(zhí)行。
如果后臺(tái)中有多個(gè)命令冗酿,可以用bg %jobnumber
將選中的命令調(diào)出辑奈。
六、kill
方法1:通過jobs命令查看job號(hào)(假設(shè)為num)已烤,然后執(zhí)行
$ kill %num
方法2:通過ps命令查看job的進(jìn)程號(hào)(PID鸠窗,假設(shè)為pid),然后執(zhí)行
$ kill pid
前臺(tái)進(jìn)程的終止:Ctrl+c
七胯究、nohup
如果想讓程序即使在關(guān)閉當(dāng)前的終端后也始終在后臺(tái)執(zhí)行(之前的&做不到)稍计,需要使用nohup命令。
nohup命令可以在你退出帳戶/關(guān)閉終端之后繼續(xù)運(yùn)行相應(yīng)的進(jìn)程裕循。
關(guān)閉終端后臣嚣,在另一個(gè)終端jobs已經(jīng)無法看到后臺(tái)跑的程序了,此時(shí)利用ps(進(jìn)程查看命令)查看進(jìn)程剥哑。
ps -aux | grep "test.sh" #ps選項(xiàng)說明: a:顯示所有程序 u:以用戶為主的格式來顯示 x:顯示所有程序硅则,不以終端機(jī)來區(qū)分
參考資料
http://m.2cto.com/os/201301/185701.html