天天看點

Linux指令nohup+screen

如果想在關閉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

完!