Linux命令nohup+screen

LiuYinChina發表於2013-09-20
如果想在關閉ssh連線後剛才啟動的程式繼續執行怎麼辦,可以使用nohup。但是如果要求第二天來的時候,一開ssh,還能檢視到昨天執行的程式的狀態,然後繼續工作,這時nohup是不行了,需要使用screen來達到這個目的。

 

nohup命令可以用來執行其他命令,並且忽略SIGHUP訊號(run a command immune to hangups, with output to a non-tty。Run COMMAND, ignoring hangup signals.)當一個虛擬終端的網路連線斷開時,作業系統向正在執行的程式傳送SIGHUP訊號(HUP = HangUP、結束通話),預設情況下這個訊號將使程式退出。

 
一 nohup

 

問題1為什麼ssh一關閉,程式就不再執行了?
元凶:SIGHUP 訊號 
讓我們來看看為什麼關掉視窗/斷開連線會使得正在執行的程式死掉。

 

在Linux/Unix中,有這樣幾個概念:
程式組(process group):一個或多個程式的集合,每一個程式組有唯一一個程式組ID,即程式組長程式的ID。
會話期(session):一個或多個程式組的集合,有唯一一個會話期首程式(session leader)。會話期ID為首程式的ID。
會話期可以有一個單獨的控制終端(controlling terminal)。與控制終端連線的會話期首程式叫做控制程式(controlling process)。當前與終端互動的程式稱為前臺程式組。其餘程式組稱為後臺程式組。
根據POSIX.1定義:
結束通話訊號(SIGHUP)預設的動作是終止程式。
當終端介面檢測到網路連線斷開,將結束通話訊號傳送給控制程式(會話期首程式)。
如果會話期首程式終止,則該訊號傳送到該會話期前臺程式組。
一個程式退出導致一個孤兒程式組中產生時,如果任意一個孤兒程式組程式處於STOP狀態,傳送SIGHUP和SIGCONT訊號到該程式組中所有程式。
結論:因此當網路斷開或終端視窗關閉後,也就是SSH斷開以後,控制程式收到SIGHUP訊號退出,會導致該會話期內其他程式退出。
 
簡而言之:就是ssh 開啟以後,bash等都是他的子程式,一旦ssh關閉,系統將所有相關程式殺掉!! 導致一旦ssh關閉,執行中的任務就取消了
 
 
例子:
我們來看一個例子。開啟兩個SSH終端視窗,在其中一個執行top命令。
[root@tivf09 root]# top
 
在另一個終端視窗,找到top的程式ID為5180,其父程式ID為5128,即登入shell。
[root@tivf09 root]# ps -ef|grep top
root      5180  5128  0 01:03 pts/0    00:00:02 top
root      5857  3672  0 01:12 pts/2    00:00:00 grep top
 
使用pstree命令可以更清楚地看到這個關係:
[root@tivf09 root]# pstree -H 5180|grep top
|-sshd-+-sshd---bash---top

 
使用ps-xj命令可以看到,登入shell(PID 5128)和top在同一個會話期,shell為會話期首程式,所在程式組PGID為5128,top所在程式組PGID為5180,為前臺程式組。
[root@tivf09 root]# ps -xj|grep 5128
 5126  5128  5128  5128 pts/0     5180 S        0   0:00 -bash
 5128  5180  5180  5128 pts/0     5180 S        0   0:50 top
 3672 18095 18094  3672 pts/2    18094 S        0   0:00 grep 5128
 
關閉第一個SSH視窗,在另一個視窗中可以看到top也被殺掉了。
[root@tivf09 root]# ps -ef|grep 5128
root     18699  3672  0 04:35 pts/2    00:00:00 grep 5128
 
問題2   為什麼守護程式就算ssh 開啟的,就算關閉ssh也不會影響其執行? 
因為他們的程式特殊,比如httpd –k start執行這個以後,他不屬於sshd這個程式組  而是單獨的程式組,所以就算關閉了ssh,和他也沒有任何關係! 
[root@CentOS5-4 ~]# pstree |grep http
     |-httpd
[root@CentOS5-4 ~]# pstree |grep top
     |-sshd-+-sshd---bash---top
 
 
結論:守護程式的啟動命令本身就是特殊的,和一般命令不同的,比如mysqld_safe 這樣的命令 一旦使用了  就是守護程式執行。所以想把一般程式改造為守護程式是不可能,
 
問題3 使用後臺執行命令&  能否將程式擺脫ssh程式組控制呢  也就是ssh關閉,後臺程式繼續執行? 
我們做一個試驗:  find / -name ‘*http*’ &
利用ctrl+d 登出以後 再進入系統  會不會看見這個命令再執行?
答案是  :命令被中止了!!
 
因為他依然屬於這個ssh程式組 就算加了&也無法擺脫!!
[root@CentOS5-4 ~]# pstree |grep find
     |-sshd-+-sshd---bash---find
 
結論就是:只要是ssh 開啟執行的一般命令,不是守護程式,無論加不加&,一旦關閉ssh,系統就會用SIGHUP終止
 
問題4  nohup能解決的問題
但是為了能夠再登出以後 依然能後臺執行,那麼我們就可以使用nohup這個命令,我們現在開始查詢find / -name ‘*http*’ &
,並且希望在後臺執行,
那麼就使用nohup:nohup find / -name "*httpd*"
此時預設地程式執行的輸出資訊放到當前資料夾的 nohup.out 檔案中去
加不加&並不會影響這個命令   只是讓程式 前臺或者後臺執行而已 
 
二 screen

 

雖然nohup很容易使用,但還是比較“簡陋”的,對於簡單的命令能夠應付過來,對於複雜的需要人機互動的任務就麻煩了。
其實我們可以使用一個更為強大的實用程式screen。流行的Linux發行版(例如Red Hat Enterprise Linux 4)通常會自帶screen實用程式,如果沒有的話,可以從GNU screen的官方網站下載。

 

 1)使用
執行screen , 按任意鍵進入子介面;
我用ping命令開始執行,如果下班了,但是想關閉ssh以後ping繼續執行,那麼按ctrl+a   再按d   這樣暫停了子介面,會顯示[detached]的字樣,這時候 我回到了父介面;
用screen –ls檢視目前子介面的狀態 screen -ls
There is a screen on: 22292.pts-3.free (Detached)
1 Socket in /tmp/screens/S-root,這裡的22292其實是子介面的pid號;
 
如果回到子介面 用screen –r 22292,一下子彈到了ping 的子介面;
 
2)更多幫助 
可以通過C-a(ctrl+a) ?來檢視所有的鍵繫結,常用的鍵繫結有:
 
C-a ?
顯示所有鍵繫結資訊
C-a w
顯示所有視窗列表
C-a C-a
切換到之前顯示的視窗
C-a c
建立一個新的執行shell的視窗並切換到該視窗
C-a n
切換到下一個視窗
C-a p
切換到前一個視窗(與C-a n相對)
C-a 0..9
切換到視窗0..9
C-a a
傳送 C-a到當前視窗
C-a d
暫時斷開screen會話
C-a k
殺掉當前視窗
C-a [
進入拷貝/回滾模式
 
其他常用選項:
 
-c file
使用配置檔案file,而不使用預設的$HOME/.screenrc
-d|-D [pid.tty.host]
不開啟新的screen會話,而是斷開其他正在執行的screen會話
-h num
指定歷史回滾緩衝區大小為num行
-list|-ls
列出現有screen會話,格式為pid.tty.host
-d -m
啟動一個開始就處於斷開模式的會話
-r sessionowner/ [pid.tty.host]
重新連線一個斷開的會話。多使用者模式下連線到其他使用者screen會話需要指定sessionowner,需要setuid-root許可權
-S sessionname
建立screen會話時為會話指定一個名字
-v
顯示screen版本資訊
-wipe [match]
同-list,但刪掉那些無法連線的會話
 
 
  
參考:http://chlotte.blog.51cto.com/318402/556540
 

相關文章