你是否是常常須要 SSH 或者 telent 遠程登陸到 Linux 服務器?你是否是常常爲一些長時間運行的任務而頭疼,好比系統備份、ftp 傳輸等等。一般狀況下咱們都是爲每個這樣的任務開一個遠程終端窗口,由於他們執行的時間太長了。必須等待它執行完畢,在此期間可不能關掉窗口或者斷開鏈接,不然這個任務就會被殺掉,一切半途而廢了。html
讓咱們來看看爲何關掉窗口/斷開鏈接會使得正在運行的程序死掉。shell
在Linux/Unix中,有這樣幾個概念:bash
根據POSIX.1定義:服務器
所以當網絡斷開或終端窗口關閉後,控制進程收到SIGHUP信號退出,會致使該會話期內其餘進程退出。網絡
咱們來看一個例子。打開兩個SSH終端窗口,在其中一個運行top命令。session
[root@localhost root]# top
在另外一個終端窗口,找到top的進程ID爲5180,其父進程ID爲5128,即登陸shell。ssh
[root@localhost 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命令能夠更清楚地看到這個關係:socket
[root@localhost root]# pstree -H 5180|grep top
使用ps-xj命令能夠看到,登陸shell(PID 5128)和top在同一個會話期,shell爲會話期首進程,所在進程組PGID爲5128,top所在進程組PGID爲5180,爲前臺進程組。網站
[root@localhost 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也被殺掉了。ui
[root@localhost 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@localhost ~]# rpm -qa|grep screen xscreensaver-4.18-5.rhel4.11``screen-4.0.2-5
簡單來講,Screen是一個能夠在多個進程之間多路複用一個物理終端的窗口管理器。Screen中有會話的概念,用戶能夠在一個screen會話中建立多個screen窗口,在每個screen窗口中就像操做一個真實的telnet/SSH鏈接窗口那樣。在screen中建立一個新的窗口有這樣幾種方式:
[root@localhost ~]# screen
Screen將建立一個執行shell的全屏窗口。你能夠執行任意shell程序,就像在ssh窗口中那樣。在該窗口中鍵入exit退出該窗口,若是這是該screen會話的惟一窗口,該screen會話退出,不然screen自動切換到前一個窗口。
[root@localhost ~]# screen vi test.c
Screen建立一個執行vi test.c的單窗口會話,退出vi將退出該窗口/會話。
C-a c
,即Ctrl鍵+a鍵,以後再按下c鍵,screen 在該會話內生成一個新的窗口並切換到該窗口。screen還有更高級的功能。你能夠不中斷screen窗口中程序的運行而暫時斷開(detach)screen會話,並在隨後時間從新鏈接(attach)該會話,從新控制各窗口中運行的程序。例如,咱們打開一個screen窗口編輯/tmp/abc文件:
[root@localhost ~]# screen vi /tmp/abc
以後咱們想暫時退出作點別的事情,好比出去散散步,那麼在screen窗口鍵入C-a d
,Screen會給出detached提示:
screen vi /tmp/abc
半個小時以後回來了,找到該screen會話:
[root@localhost ~]# screen -ls There is a screen on: 39264.pts-1.localhost (Detached) 1 Socket in /tmp/screens/S-root.
從新鏈接會話:
[root@localhost ~]# screen -r 39264
看看出現什麼了,太棒了,一切都在。繼續幹吧。
你可能注意到給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@localhost 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
[root@localhost root]# screen –ls There are screens on: 8736.pts-1.localhost (Detached) 8462.pts-0.localhost (Detached) 2 Sockets in /root/.screen. [root@localhost root]# screen –r 8736
若是因爲某種緣由其中一個會話死掉了(例如人爲殺掉該會話),這時screen -list會顯示該會話爲dead狀態。使用screen -wipe命令清除該會話:
[root@localhost root]# kill -9 8462 [root@localhost root]# screen -ls There are screens on: 8736.pts-1.localhost (Detached) 8462.pts-0.localhost (Dead ???) Remove dead screens with 'screen -wipe'. 2 Sockets in /root/.screen. [root@localhost root]# screen -wipe There are screens on: 8736.pts-1.localhost (Detached) 8462.pts-0.localhost (Removed) 1 socket wiped out. 1 Socket in /root/.screen. [root@localhost root]# screen -ls There is a screen on: 8736.pts-1.localhost (Detached) 1 Socket in /root/.screen. [root@localhost root]#
-d –m 選項是一對頗有意思的搭檔。他們啓動一個開始就處於斷開模式的會話。你能夠在隨後須要的時候鏈接上該會話。有時候這是一個頗有用的功能,好比咱們可使用它調試後臺程序。該選項一個更經常使用的搭配是:-dmS sessionname啓動一個初始狀態斷開的screen會話:
[root@localhost tianq]# screen -dmS mygdb gdb execlp_test #鏈接該會話: [root@localhost tianq]# screen -r mygdb
先來看看如何使用screen解決SIGHUP問題,好比如今咱們要ftp傳輸一個大文件。若是按老的辦法,SSH登陸到系統,直接ftp命令開始傳輸,以後。若是網絡速度還能夠,恭喜你,不用等太長時間了;若是網絡很差,老老實實等着吧,只能傳輸完畢再斷開SSH鏈接了。讓咱們使用screen來試試。
SSH登陸到系統,在命令行鍵入screen。
[root@localhost root]# screen
在screen shell窗口中輸入ftp命令,登陸,開始傳輸。不肯意等了?OK,在窗口中鍵入C-a d:
而後。。退出SSH登陸?隨你怎樣,只要別殺掉screen會話。
是否是很方便?更進一步,其實咱們能夠利用screen這種功能來管理你的遠程會話,保存你全部的工做內容。你是否是每次登陸到系統都要開不少窗口,而後天天都要重複打開關閉這些窗口?讓screen來幫你「保存」吧,你只須要打開一個ssh窗口,建立須要的screen窗口,退出的時候C-a d「保存」你的工做,下次登陸後直接screen -r
最好能給每一個窗口起一個名字,這樣好記些。使用C-a A給窗口起名字。使用C-a w能夠看到這些窗口名字,可能名字出現的位置不一樣。
啓動時添加選項-L(Turn on output logging.),會在當前目錄下生成screenlog.0文件。
[root@k8s-master1 ~]# screen -L -dmS test [root@k8s-master1 ~]# ls screenlog.0 screenlog.0
screen -L -dmS test的意思是啓動一個開始就處於斷開模式的會話,會話的名稱是test。
screen -r test鏈接該會話,在會話中的全部屏幕輸出都會記錄到screenlog.0文件。
不加選項-L,啓動後,在screen session下按ctrl+a H,一樣會在當前目錄下生成screenlog.0文件。
第一次按下ctrl+a H,屏幕左下角會提示Creating logfile "screenlog.0".,開始記錄日誌。
再次按下ctrl+a H,屏幕左下角會提示Logfile "screenlog.0" closed.,中止記錄日誌。
上面兩個方法有個缺點:當建立多個screen會話的時候,每一個會話都會記錄日誌到screenlog.0文件。screenlog.0中的內容就比較混亂了。
解決方法以下,讓每一個screen會話窗口有單獨的日誌文件。
在screen配置文件/etc/screenrc最後添加下面一行:
logfile /tmp/screenlog_%t.log
%t是指window窗口的名稱,對應screen的-t參數。因此咱們啓動screen的時候要指定窗口的名稱,例如:
[root@k8s-master1 ~]# screen -L -t window1 -dmS test [root@k8s-master1 ~]# ll /tmp/screenlog_window1.log -rw-r--r-- 1 root root 44 Feb 18 19:55 /tmp/screenlog_window1.log
screen -L -t window1 -dmS test的意思是啓動test會話,test會話的窗口名稱爲window1。屏幕日誌記錄在/tmp/screenlog_window1.log。若是啓動的時候不加-L參數,在screen session下按ctrl+a H,日誌也會記錄在/tmp/screenlog_window1.log。
Screen提供了豐富強大的定製功能。你能夠在Screen的默認兩級配置文件/etc/screenrc和$HOME/.screenrc中指定更多,例如設定screen選項,定製綁定鍵,設定screen會話自啓動窗口,啓用多用戶模式,定製用戶訪問權限控制等等。若是你願意的話,也能夠本身指定screen配置文件。
以多用戶功能爲例,screen默認是以單用戶模式運行的,你須要在配置文件中指定multiuser on 來打開多用戶模式,經過acl*(acladd,acldel,aclchg...)命令,你能夠靈活配置其餘用戶訪問你的screen會話。更多配置文件內容請參考screen的man頁。