Shell的后臺運行(&)與nohup

shell的后臺運行(&)與nohup

簡述

在shell腳本中當我們需要把一個任務放在后臺運行時嘁信,通常我們會使用&符號:

subcommand &

此時主進程會繼續(xù)往下執(zhí)行话速,而子進程會在后臺啟動運行。

于此同時塌碌,我們常會看到nohup會和后臺任務一起使用,格式是:

nohup subcommand &

nohup在這里起了什么角色呢浇揩。

nohup

nohup起兩個作用:

  1. 正如名字所聲稱的熊昌,忽略所有發(fā)送給子命令的掛斷(SIGHUP)信號
nohup subcommand &

這樣所有發(fā)給subcommand的SIGHUP信號都被忽略绽榛,subcommand就不會收到SIGHUP信號。

什么是SIGHUP信號呢婿屹?
簡單的理解可以是終端結束時灭美,操作系統(tǒng)會發(fā)送SIGHUP信號到后臺進程。

  1. 重定向子命令的標準輸出(stdout)和標準錯誤(stderr)
    我們可以在終端看到如下輸出:
nohup: appending output to "nohup.out"

表示subcommand的標準輸出和標準錯誤被重定向到nohup.out文件昂利;如果沒有使用nohup方式届腐,則subcommand的標準輸出和標準錯誤是復用父進程的標準輸出和標準錯誤铁坎。

舉例

例子1:后臺運行(&)

$ cat testshell0.sh 
#!/bin/bash

#trap "echo \"SIGHUP is received\"" 1

for i in {1..10000}; do
       echo "$i: in $0"
  1>&2 echo "$i: in $0"

  sleep 1
done
$ cat testshell1.sh  
#!/bin/bash

./testshell0.sh &

for i in {1..10000}; do
  echo "$i: in $0"
  sleep 1
done
$ ./testshell1.sh 
1: in ./testshell1.sh
1: in ./testshell0.sh
1: in ./testshell0.sh
2: in ./testshell1.sh
2: in ./testshell0.sh
2: in ./testshell0.sh
CTRL-C(^C)
$ 3: in ./testshell0.sh
3: in ./testshell0.sh
4: in ./testshell0.sh
5: in ./testshell0.sh

腳本testshell1.sh以后臺方式(&)調用testshell0.sh;
我們看到testshell1.sh和testshell0.sh的輸出都在屏幕上犁苏,而當(CTRL-C)殺掉testshell1.sh的時候硬萍,testshell0.sh繼續(xù)在運行,繼續(xù)往屏幕打印輸出围详。

例子2:nohup方式后臺運行(&)

$ cat testshell0.sh 
#!/bin/bash

#trap "echo \"SIGHUP is received\"" 1

for i in {1..10000}; do
       echo "$i: in $0"
  1>&2 echo "$i: in $0"

  sleep 1
done
$ cat testshell1.sh  
#!/bin/bash

nohup ./testshell0.sh &

for i in {1..10000}; do
  echo "$i: in $0"
  sleep 1
done
$ ./testshell1.sh 
nohup: appending output to "nohup.out"
1: in ./testshell1.sh
1: in ./testshell0.sh
1: in ./testshell0.sh
2: in ./testshell1.sh
2: in ./testshell0.sh
2: in ./testshell0.sh
CTRL-C(^C)
$

腳本testshell1.sh以nohup的方式在后臺(&)調用testshell0.sh朴乖;
我們看到testshell1.sh的輸出在屏幕上,testshell0.sh的輸出在文件nohup.out里:

$ tail -f nohup.out
1: in ./testshell0.sh
1: in ./testshell0.sh
2: in ./testshell0.sh
2: in ./testshell0.sh
3: in ./testshell0.sh
3: in ./testshell0.sh

而當(CTRL-C)殺掉testshell1.sh的時候助赞,testshell0.sh繼續(xù)在運行买羞,繼續(xù)往nohup.log里面打印輸出。

在這兩個例子中雹食,當testshell1.sh已經停止時畜普,testshell0.sh并不會結束,而都能繼續(xù)運行婉徘。

例子3:后臺運行(&) + 關閉終端

代碼和運行方法同例子1漠嵌,只是在運行時關閉終端。
結果testshell1.sh和testshell0.sh都結束了盖呼。

$ ps -ef | grep testshell | grep -v grep
$ 

例子4:nohup方式后臺運行(&) + 關閉終端

代碼和運行方法同例子2儒鹿,只是在運行時關閉終端。
結果testshell1.sh結束了几晤,而testshell0.sh還在繼續(xù)運行约炎。

$ ps -ef | grep testshell | grep -v grep
<uid>  <pid>     1  0 22:29 ?        00:00:00 /bin/bash ./testshell0.sh
$ 

需要注意的是,此時testshell0.sh的父進程變成了進程號1蟹瘾,而不是testshell1.sh圾浅,因為testshell1.sh已經死了,操作系統(tǒng)接管了testshell1.sh進程憾朴。

對比例子3和例子4狸捕,差別是是否以nohup的方式運行testshell0.sh,在例子3不是以nohup的方式众雷,這樣當終端結束的時候灸拍,testshell0.sh會收到SIGHUP信號,缺省的處理方式是殺掉自己砾省,所以testshell0.sh也死了鸡岗;而例子4使用了nohup方式,他會忽略SIGHUP信號编兄,所以testshell0.sh繼續(xù)運行轩性。

看例子5,注意其中的區(qū)別

例子5:后臺運行(&) + 關閉父進程+關閉終端

代碼和運行方法同例子1狠鸳。
啟動進程testshell1.sh

$ ./testshell1.sh 
1: in ./testshell1.sh
1: in ./testshell0.sh
1: in ./testshell0.sh
2: in ./testshell1.sh
2: in ./testshell0.sh
2: in ./testshell0.sh
3: in ./testshell1.sh
3: in ./testshell0.sh
3: in ./testshell0.sh

此時testshell1.sh和testshell0.sh同時在運行揣苏,往終端打印輸出悯嗓。

$ ps -ef | grep testshell | grep -v grep
<uid>  13789 13642  0 22:34 pts/10   00:00:00 /bin/bash ./testshell1.sh
<uid>  13790 13789  0 22:34 pts/10   00:00:00 /bin/bash ./testshell0.sh

殺掉進程testshell1.sh
屏幕繼續(xù)打印testshell0.sh的輸出。

CTRL-C(^C)
$ 4: in ./testshell0.sh
4: in ./testshell0.sh
5: in ./testshell0.sh
5: in ./testshell0.sh

查看進程狀態(tài)

$ ps -ef | grep testshell | grep -v grep
<uid>  13790     1  0 22:34 pts/10   00:00:00 /bin/bash ./testshell0.sh
$ 

子進程testshell0.sh繼續(xù)在運行舒岸。

此時我們退出終端绅作,再查看進程狀態(tài)

$ ps -ef | grep testshell | grep -v grep
<uid>  13790     1  0 22:34 pts/10   00:00:00 /bin/bash ./testshell0.sh
$ 

為什么子進程testshell0.sh還在呢?
既然終端已經退出了蛾派,按理操作系統(tǒng)應該給testshell0.sh發(fā)送SIGHUP信號俄认,然后導致testshell0.sh退出啊洪乍?
原因是testshell0.sh是以后臺任務的方式由testshell1.sh提交眯杏,當testshell1.sh已經退出后,testshell0.sh變成了孤兒進程壳澳,操作系統(tǒng)自動收集這些孤兒進程岂贩,此時我們看到testshell0.sh的父進程已經變成進程號1了,這樣testshell0.sh和當前終端已經沒有了關系巷波,他們失去了聯(lián)系萎津,從而當當前終端結束的時候,testshell0.sh不會也不需要得到什么消息抹镊,那么也就不會收到SIGHUP信號了锉屈。

這鏈接里面[SIGHUP信號與控制終端]https://blog.csdn.net/cugxueyu/article/details/2046565,非常清楚的介紹了兩者的關系垮耳,供參考颈渊。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市终佛,隨后出現的幾起案子俊嗽,更是在濱河造成了極大的恐慌,老刑警劉巖铃彰,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绍豁,死亡現場離奇詭異,居然都是意外死亡牙捉,警方通過查閱死者的電腦和手機竹揍,發(fā)現死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹃共,“玉大人,你說我怎么就攤上這事驶拱∷。” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵蓝纲,是天一觀的道長阴孟。 經常有香客問我晌纫,道長,這世上最難降的妖魔是什么永丝? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任锹漱,我火速辦了婚禮,結果婚禮上慕嚷,老公的妹妹穿的比我還像新娘哥牍。我一直安慰自己,他們只是感情好喝检,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布嗅辣。 她就那樣靜靜地躺著,像睡著了一般挠说。 火紅的嫁衣襯著肌膚如雪澡谭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天损俭,我揣著相機與錄音蛙奖,去河邊找鬼。 笑死杆兵,一個胖子當著我的面吹牛雁仲,可吹牛的內容都是我干的。 我是一名探鬼主播拧咳,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼伯顶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了骆膝?” 一聲冷哼從身側響起祭衩,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阅签,沒想到半個月后掐暮,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡政钟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年路克,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片养交。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡精算,死狀恐怖,靈堂內的尸體忽然破棺而出碎连,到底是詐尸還是另有隱情灰羽,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站廉嚼,受9級特大地震影響玫镐,放射性物質發(fā)生泄漏。R本人自食惡果不足惜怠噪,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一恐似、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧傍念,春花似錦矫夷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秦陋,卻和暖如春蔓彩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驳概。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工赤嚼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人顺又。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓更卒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親稚照。 傳聞我的和親對象是個殘疾皇子蹂空,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容