你是否是常常須要 SSH 或者 telent 遠程登陸到 Linux 服務器?你是否是常常爲一些長時間運行的任務而頭疼,好比系統備份、ftp 傳輸等等。一般狀況下咱們都是爲每個這樣的任務開一個遠程終端窗口,由於他們執行的時間太長了。必須等待它執行完畢,在此期間可不能關掉窗口或者斷開鏈接,不然這個任務就會被殺掉,一切半途而廢了。html
讓咱們來看看爲何關掉窗口/斷開鏈接會使得正在運行的程序死掉。linux
在Linux/Unix中,有這樣幾個概念:shell
- 進程組(process group):一個或多個進程的集合,每個進程組有惟一一個進程組ID,即進程組長進程的ID。
- 會話期(session):一個或多個進程組的集合,有惟一一個會話期首進程(session leader)。會話期ID爲首進程的ID。
- 會話期能夠有一個單獨的控制終端(controlling terminal)。與控制終端鏈接的會話期首進程叫作控制進程(controlling process)。當前與終端交互的進程稱爲前臺進程組。其他進程組稱爲後臺進程組。
根據POSIX.1定義:bash
- 掛斷信號(SIGHUP)默認的動做是終止程序。
- 當終端接口檢測到網絡鏈接斷開,將掛斷信號發送給控制進程(會話期首進程)。
- 若是會話期首進程終止,則該信號發送到該會話期前臺進程組。
- 一個進程退出致使一個孤兒進程組中產生時,若是任意一個孤兒進程組進程處於STOP狀態,發送SIGHUP和SIGCONT信號到該進程組中全部進程。
所以當網絡斷開或終端窗口關閉後,控制進程收到SIGHUP信號退出,會致使該會話期內其餘進程退出。服務器
咱們來看一個例子。打開兩個SSH終端窗口,在其中一個運行top命令。網絡
[root@tivf09 root]# top
在另外一個終端窗口,找到top的進程ID爲5180,其父進程ID爲5128,即登陸shell。session
[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命令能夠更清楚地看到這個關係:ssh
[root@tivf09 root]# pstree -H 5180|grep top |-sshd-+-sshd---bash---top
使用ps-xj命令能夠看到,登陸shell(PID 5128)和top在同一個會話期,shell爲會話期首進程,所在進程組PGID爲5128,top所在進程組PGID爲5180,爲前臺進程組。socket
[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也被殺掉了。ide
[root@tivf09 root]# ps -ef|grep 5128 root 18699 3672 0 04:35 pts/2 00:00:00 grep 5128
若是咱們能夠忽略SIGHUP信號,關掉窗口應該就不會影響程序的運行了。nohup命令能夠達到這個目的,若是程序的標準輸出/標準錯誤是終端,nohup默認將其重定向到nohup.out文件。值得注意的是nohup命令只是使得程序忽略SIGHUP信號,還須要使用標記&把它放在後臺運行。
nohup <command> [argument…] &
雖然nohup很容易使用,但仍是比較「簡陋」的,對於簡單的命令可以應付過來,對於複雜的須要人機交互的任務就麻煩了。
其實咱們可使用一個更爲強大的實用程序screen。流行的Linux發行版(例如Red Hat Enterprise Linux 4)一般會自帶screen實用程序,若是沒有的話,能夠從GNU screen的官方網站下載。
[root@tivf06 ~]# rpm -qa|grep screen xscreensaver-4.18-5.rhel4.11
簡單來講,Screen是一個能夠在多個進程之間多路複用一個物理終端的窗口管理器。Screen中有會話的概念,用戶能夠在一個screen會話中建立多個screen窗口,在每個screen窗口中就像操做一個真實的telnet/SSH鏈接窗口那樣。在screen中建立一個新的窗口有這樣幾種方式:
1.直接在命令行鍵入screen命令
[root@tivf06 ~]# screen
Screen將建立一個執行shell的全屏窗口。你能夠執行任意shell程序,就像在ssh窗口中那樣。在該窗口中鍵入exit退出該窗口,若是這是該screen會話的惟一窗口,該screen會話退出,不然screen自動切換到前一個窗口。
2.Screen命令後跟你要執行的程序。
[root@tivf06 ~]# screen vi test.c
Screen建立一個執行vi test.c的單窗口會話,退出vi將退出該窗口/會話。
3.以上兩種方式都建立新的screen會話。咱們還能夠在一個已有screen會話中建立新的窗口。在當前screen窗口中鍵入C-a c
,即Ctrl鍵+a鍵,以後再按下c鍵,screen 在該會話內生成一個新的窗口並切換到該窗口。
screen還有更高級的功能。你能夠不中斷screen窗口中程序的運行而暫時斷開(detach)screen會話,並在隨後時間從新鏈接(attach)該會話,從新控制各窗口中運行的程序。例如,咱們打開一個screen窗口編輯/tmp/abc文件:
[root@tivf06 ~]# screen vi /tmp/abc
以後咱們想暫時退出作點別的事情,好比出去散散步,那麼在screen窗口鍵入C-a d
,Screen會給出detached提示:
半個小時以後回來了,找到該screen會話:
[root@tivf06 ~]# screen -ls There is a screen on: 16582.pts-1.tivf06 (Detached) 1 Socket in /tmp/screens/S-root.
從新鏈接會話:
[root@tivf06 ~]# screen -r 16582
看看出現什麼了,太棒了,一切都在。繼續幹吧。
你可能注意到給screen發送命令使用了特殊的鍵組合C-a。這是由於咱們在鍵盤上鍵入的信息是直接發送給當前screen窗口,必須用其餘方式向screen窗口管理器發出命令,默認狀況下,screen接收以C-a開始的命令。這種命令形式在screen中叫作鍵綁定(key binding),C-a叫作命令字符(command character)。
能夠經過C-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-a ?命令能夠看到, 默認的命令字符(Command key)爲C-a,轉義C-a(literal ^a)的字符爲a:
由於screen把C-a看做是screen命令的開始,因此若是你想要screen窗口接收到C-a字符,就要輸入C-a a。Screen也容許你使用-e選項設置本身的命令字符和轉義字符,其格式爲:
-exy x爲命令字符,y爲轉義命令字符的字符
下面命令啓動的screen會話指定了命令字符爲C-t,轉義C-t的字符爲t,經過C-t ?命令能夠看到該變化。
[root@tivf18 root]# screen -e^tt
其餘經常使用的命令選項有:
-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,但刪掉那些沒法鏈接的會話 |
下例顯示當前有兩個處於detached狀態的screen會話,你可使用screen -r <screen_pid>從新鏈接上:
[root@tivf18 root]# screen –ls There are screens on: 8736.pts-1.tivf18 (Detached) 8462.pts-0.tivf18 (Detached) 2 Sockets in /root/.screen. [root@tivf18 root]# screen –r 8736 |
若是因爲某種緣由其中一個會話死掉了(例如人爲殺掉該會話),這時screen -list會顯示該會話爲dead狀態。使用screen -wipe命令清除該會話:
[root@tivf18 root]# kill -9 8462 [root@tivf18 root]# screen -ls There are screens on: 8736.pts-1.tivf18 (Detached) 8462.pts-0.tivf18 (Dead ???) Remove dead screens with 'screen -wipe'. 2 Sockets in /root/.screen. [root@tivf18 root]# screen -wipe There are screens on: 8736.pts-1.tivf18 (Detached) 8462.pts-0.tivf18 (Removed) 1 socket wiped out. 1 Socket in /root/.screen. [root@tivf18 root]# screen -ls There is a screen on: 8736.pts-1.tivf18 (Detached) 1 Socket in /root/.screen. [root@tivf18 root]# |
-d –m 選項是一對頗有意思的搭檔。他們啓動一個開始就處於斷開模式的會話。你能夠在隨後須要的時候鏈接上該會話。有時候這是一個頗有用的功能,好比咱們可使用它調試後臺程序。該選項一個更經常使用的搭配是:-dmS sessionname
啓動一個初始狀態斷開的screen會話:
[root@tivf06 tianq]# screen -dmS mygdb gdb execlp_test
鏈接該會話:
[root@tivf06 tianq]# screen -r mygdb
先來看看如何使用screen解決SIGHUP問題,好比如今咱們要ftp傳輸一個大文件。若是按老的辦法,SSH登陸到系統,直接ftp命令開始傳輸,以後。。若是網絡速度還能夠,恭喜你,不用等太長時間了;若是網絡很差,老老實實等着吧,只能傳輸完畢再斷開SSH鏈接了。讓咱們使用screen來試試。
SSH登陸到系統,在命令行鍵入screen。
[root@tivf18 root]# screen
在screen shell窗口中輸入ftp命令,登陸,開始傳輸。不肯意等了?OK,在窗口中鍵入C-a d:
而後。。退出SSH登陸?隨你怎樣,只要別殺掉screen會話。
是否是很方便?更進一步,其實咱們能夠利用screen這種功能來管理你的遠程會話,保存你全部的工做內容。你是否是每次登陸到系統都要開不少窗口,而後天天都要重複打開關閉這些窗口?讓screen來幫你「保存」吧,你只須要打開一個ssh窗口,建立須要的screen窗口,退出的時候C-a d「保存」你的工做,下次登陸後直接screen -r <screen_pid>就能夠了。
最好能給每一個窗口起一個名字,這樣好記些。使用C-a A給窗口起名字。使用C-a w能夠看到這些窗口名字,可能名字出現的位置不一樣。使用putty:
使用telnet:
Screen提供了豐富強大的定製功能。你能夠在Screen的默認兩級配置文件/etc/screenrc和$HOME/.screenrc中指定更多,例如設定screen選項,定製綁定鍵,設定screen會話自啓動窗口,啓用多用戶模式,定製用戶訪問權限控制等等。若是你願意的話,也能夠本身指定screen配置文件。
以多用戶功能爲例,screen默認是以單用戶模式運行的,你須要在配置文件中指定multiuser on 來打開多用戶模式,經過acl*(acladd,acldel,aclchg...)命令,你能夠靈活配置其餘用戶訪問你的screen會話。更多配置文件內容請參考screen的man頁。
- 「Advanced Programming in the UNIX® Environment: Second Edition」 W. Richard Stevens, Stephen A. Rago 提供了更多關於Linux/Unix進程關係、信號的知識。
- GNU Screen的官方網站:http://www.gnu.org/software/screen/
- Screen的man page提供了最詳細的信息:http://www.slac.stanford.edu/comp/unix/package/epics/extensions/iocConsole/screen.1.html
田強,中國軟件開發中心 Tivoli 部門軟件工程師,負責 IBM 產品TMF(Tivoli Management Framework)的維護和客戶支持工做,熱愛 Linux。
原文地址:http://www.ibm.com/developerworks/cn/linux/l-cn-screen/