Shell脚本:后台运行
1.?名詞解釋
| 名詞(中文) | 名詞(英文) | 解釋 |
| 會話 | Session | 每打開一次終端(本地或遠程)登錄Linux,都會生成一個新的會話;除此之外,程序中也可以調用函數setsid創建一個新的會話;腳本也可以調用命令setsid創建一個新的會話。新建的會話無控制終端。 |
| 會話ID | SessionID | 用來標識一個會話,同一時刻不同會話的ID不會相同,是一個int類型的整數值。 |
| 用戶 | User | 指能登錄Linux的用戶帳號 |
| 用戶ID | UserID | 用來唯一標識一個用戶 |
| 偽終端或叫虛擬終端 | ?pty (Pseudo?Terminal) | ? |
| 控制終端 | tty (Teletypewriter或Teletype) | 字符型設備 |
| ? | pts (pseudo-terminal?slave) | pty的實現方法,分兩端:一端叫master,另一端叫slave。可打開的最多pts數為/proc/sys/kernel/pty/max,當前已打開的pts數為/proc/sys/kernel/pty/nr。 |
?
2.?什么是守護進程?
在后臺運行的進程不一定是守護進程!一個進程要成為守護進程,必須做到以下兩點:
1)?在后臺運行
2)?脫離了終端
2.1.?后臺運行
要使一個進程在后臺運行,代碼中可以通過fork子進程來實現,而命令行或腳本中可以通過使用“&”來實現。
fork之后,子進程會繼承父進程的SessionID,調用execve()后的進程的SessionID不會改變。
2.2.?解釋關系
子進程從父進程繼承了:SessionID、進程組ID和打開的終端。子進程如果要脫離這些,代碼中可通過調用setsid來實現。,而命令行或腳本中可以通過使用命令setsid來運行程序實現。setsid幫助一個進程脫離從父進程繼承而來的已打開的終端、隸屬進程組和隸屬的會話。
需要注意,代碼中調用setsid是有條件的:即調用進程自己不能是進程組長。因此,調用setsid之前需要先fork,然后由產生的子進程調用setsid。
3.?以“&”方式運行有何問題?
以“&”方式可以將一個前臺進程以后臺方式運行,但是如果它是一個終端的job,則如果向終端收到SIGHUP信號,終端也會向它的所有job發送SIGHUP,這樣以“&”方式運行的進程則會因為收到SIGHUP則退出。
當用戶注銷(logout)或者網絡斷開時,終端會收到?SIGHUP(hangup)信號從而關閉其所有子進程。
早期的Unix,終端通過Modem和系統通訊,當用戶注銷(logout)時,Modem就會掛斷(hangup)電話;當Modem斷開時,會給終端發SIGHUP來通知終端關閉所有子進程。
4.?setsid&setuid
| setsid命令或函數 | setuid函數(相對應的命令為chmod) |
| 1)?創建一個會話 2)?調用進程將成為會話的組長 3)?調用進程將成為進程組的組長 4)?調用進程將脫離控制終端(tty) 5)?會話ID和進程組ID都和調用進程的PID相同 | 1)?設置調用進程的真實用戶ID、有效用戶ID和保存用戶ID |
?
按下“ctrl+z”會觸發SIGTSTP,注意不是SIGSTOP,這兩個信號的區別是前者可以捕獲,而后者不可以。進程收到這兩個信號后,都進入STOP狀態,使用ps?aux看到的狀態值為“T”,可以通過發送信號SIGCONT重新回到運行狀態。
4.1.?setuid應用場景
1)?以root啟動,但以其它用戶身份運行,常見于Webserver,因為需要監聽80端口,不得不以root啟動,但root權限過大,因此運行經常會從root切換到nobody等用戶;
2)?開發中經常需要讓非root用戶能夠去gdb一些root啟動的進程,這個時候只開放gdb等少數一些命令給非root用戶。
5.讓shell腳本后臺運行的方法
當使用ssh連接到服務器運行程序時,用戶注銷(logout)或者網絡斷開時,終端會收到 HUP(hangup)信號從而關閉其所有子進程。但這往往不是我們想要的結果。為了避免這種情況的發生,讓程序能夠在服務器上正常運行,的解決辦法就有兩種途徑:
- 讓進程忽略HUP信號;
- 讓進程運行在新的會話里從而成為不屬于此終端的子進程。
nohup … &
nohup命令用途就是讓提交的命令忽略HUP信號;&命令用途是讓提交的命令在后臺運行。同時使用nohup ... &可以讓提交的命令忽略HUP信號,并將該命令放在后臺運行。
e.g.:nohup sh big_task.sh > big_task.log 2>&1
Q:nohup 和 nohup … & 的區別?
A:nohup僅表示讓提交的命令忽略hangup信號,但該命令仍然在前臺運行,當前的shell會被阻塞,無法繼續進行操作。但可以通過?ctrl-z將當前的命令掛起到后臺,然后再使用bg命令讓其在后臺運行,這樣就可以達到和使用nohup ... &同樣的效果
Q:僅使用 & 命令會如何?
A:僅使用&命令僅會將命令放在后臺執行,但仍然可能會受到HUP信號的影響。但此時可以通過使用disown -h命令讓其忽略HUP信號
setsid
setsid可以讓提交的命令在一個新的session中運行,新的進程不屬于接受hangup信號的終端的子進程,這樣即使ssh連接中斷,新的進程也不會受到影響。
screen
screen可以用來創建一個新的session,它不屬于ssh連接進程的子進程,因而不需要費心考慮HUP信號。
jobs
通過以下命令,我們可以對放入到后臺的命令進行控制
查看當前終端下的后臺進程:
直接執行:jobs
將查看到的某個后臺進程放回到前臺:
直接輸入:fg %jobid?//這里的jobid是通過jobs命令中看到的進程前[]中的數字。
將當前正在前臺運行的進程放到后臺運行:
先敲下快捷鍵:ctrl +z //暫停當前正在運行的進程。
再執行:bg
終止當前正在前臺運行的進程:
直接敲下快捷鍵:ctrl +c
disown
亡羊補牢,為沒有使用nohup與setsid的進程加上忽略HUP信號的功能。
使用方法:
將當前正在前臺運行的進程放到后臺運行(ctrl+z和bg);
然后執行disown -h %jobid?//這里的jobid是通過jobs命令中看到的進程前[]中的數字。
總結
以上是生活随笔為你收集整理的Shell脚本:后台运行的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络NAT、桥接与主机模式
- 下一篇: 网页设计与开发:HTML、CSS、Jav