一、背景
在linux命令行中執行程序,程序通常會占用當前終端,如果不啟動新的終端就沒法執行其他操作。簡單可以通過'&'將程序放到后台執行,但是這種方法有個問題就是,一旦連接遠程服務器的網絡異常或者本機ssh客戶端、系統等關閉亦或出現問題導致連接斷開,那么放到后台執行的程序就會被終止。
對於需要長時間運行的守護進程或者服務端程序這種異常斷開造成的進程終止不可接受。下面就介紹三種解決這種問題的通用方案(不涉及程序改造)
二、nohup命令
在啟動程序命令后面添加&將程序放到后台作業隊列中,管理任務隊列中任務可以通過jobs等命令。
但是任務隊列中的任務通常情況下,其父進程都是當前終端的shell進程。而一旦父進程退出,則會發送hangup信號給所有子進程,子進程收到hangup以后也會退出。我們可以通過讓后台進程忽略來自父進程的hangup信號或者修改后台進程的父進程id來避免后台進程退出。使用nohup命令執行的命令nohup ./tesh.sh & 可以忽略hangup信號(需要啟動程序時將程序放到后台執行,否則關閉終端依然會導致進程結束),使用setsid命令 setsid ./test.sh & 可以將當前程序的父進程設置為init進程,這樣就不會收到當前shell進程發出的hangup信號了。具體用法如下:
新啟動程序
|
nohup ./test.sh >log 2>&1 &
|
setsid ./test.sh >log 2>&1 &
|
已運行程序
|
nohup -p PID
|
disown -h %n
|
注:nohup命令會將所執行的命令的標准輸出重定向到當前目錄的nohup.out文件中(如果命令中沒有重定向標准輸出),但是不會重定向標准錯誤輸出。其余的setsid、disown只是修改進程的sid,使其與當前shell脫離,但是並沒有改變原命令的標准輸出、標准錯誤輸出,所以這些后台運行的進程,當需要標准輸出或標准錯誤輸出的時候,發現默認的輸出位置終端不可用,就會報異常退出。因此,
在運行后台進程時,盡量將利用 >log 2>&1 對命令的輸出進行重定向(如表格中第一行)。
三、screen命令
GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了統一的管理多個會話的界面和相應的功能,大部分Linux發行版都默認帶有screen。通過將screen會話與當前終端shell進程detach來避免當前終端shell的異常導致的screen中運行的程序的終止。
screen -S NAME
|
screen -S sxhlinux
|
新建一個名為sxhlinux的screen會話
|
screen -ls
|
screen -ls
|
查看當前系統中所有的screen會話
|
screen -d NAME
|
screen -d sxhlinux
|
將sxhlinux會話與當前shell終端分離
|
screen -r NAME
|
screen -r sxhlinux
|
在當前shell進程中與名為sxhlinux的進程重新連接
|
screen -R NAME
|
screen -R sxhlinux
|
同-r選項,另外如果sxhlinux不存在,
就會重新新建一個名為sxhlinux的screen會話
|
screen -x NAME
|
screen -x sxhlinux
|
多個終端同時操作名為sxhlinux的screen會話,操作同步可見
|
在每個screen 會話中都有如下快捷鍵可以使用
ctrl-a c
|
在當前會話中創建一個新的的shell窗口
|
ctrl-a n/p
|
切換到下/上一個窗口
|
ctrl-a d
|
使當前會話與原shell detach
|
ctrl-a w
|
列出當前會話中的所有窗口
|
ctrl-a k
|
關閉當前窗口
|
ctrl-a x/q
|
鎖定、解鎖當前窗口
|
ctrl-a [/]
|
[啟動復制模式(vi操作習慣),第一次空格鍵表示開始復制,第二次空格表示結束復制;
]將[復制的內容粘貼到當前位置
|
ctrl-a S/|
|
將當前屏幕水平/垂直分成兩部分,可以通過ctrl-a TAB來切換
|
可以修改/etc/screenrc或者~/.screenrc配置文件來配置screen,選項vbell off/on 控制錯誤閃屏提醒。本文關注點在保證用戶程序不因終端、網絡異常等問題造成程序運行中斷,因此這里有關screen只進行簡單的介紹,有興趣的可以搜索相關文章或者看官方document。
四、tmux命令
雖然screen很好用,但是已經很多年沒有添加新特性了,還存在一些bug。作為screen的替代者,tmux在各方面完全可以替代甚至超過screen,唯一的缺點是Linux發行版沒有默認安裝tmux,需要用戶聯網安裝。下面就簡單介紹tmux的使用方法:
tmux new -s NAME
|
tmux new -s sxhlinux
|
創建一個
|
tmux detach -s NAME
|
tmux detach -s sxhlinux
|
將sxhlinux會話分離
|
tmux attach -t NAME
|
tmux a -t sxhlinux
|
重新連接sxhlinux會話
|
tmux ls
|
tmux ls
|
列出當前所有的tmux會話
|
tmux lsc [-t NAME]
|
tmux lsc [-t sxhlinux]
|
列出所有[連接到sxhlinux]的客戶端
|
tmux rename -t OLD NEW
|
tmux rename -t sxh sxhlinux
|
將會話sxh重命名為sxhlinux
|
tmux kill-session -t NAME
|
tmux kill-session -t sxhlinux
|
關閉sxhlinux會話
|
tmux默認的快捷鍵組合前綴為ctrl b,不過為了和screen習慣保持一致,我們可以修改tmux的配置文件~/.tmux.conf來講組合前綴改成ctrl a
ctrl-a c
|
同screen
|
ctrl-a d
|
同screen
|
ctrl-a f
|
在當前會話所有打開的窗口中搜索文本
|
ctrl-a n/p
|
同screen
|
ctrl-a &
|
關閉當前窗口
|
ctrl-a x
|
關閉當前會話
|
修改的tmux配置文件如下(注:#以及后面的內容僅做說明,實際使用的時候請刪除)
set -g prefix C-a #配置快捷鍵前綴為ctrl a unbind C-b #取消快捷鍵前綴ctrl b unbind '%' #取消左右分pane的快捷鍵 % bind | splitw -h #指定左右分pane的快捷鍵 | bind k selectp -U #指定選擇上方pane的快捷鍵 k bind j selectp -D #指定選擇上方pane的快捷鍵 j bind h selectp -L #指定選擇上方pane的快捷鍵 h bind l selectp -R #指定選擇上方pane的快捷鍵 l
通常情況下,如果系統重啟原來的tmux會話就會丟失(因為tmux由一個server進程來保存相關會話信息,系統重啟原來的server進程消失,所以之前的tmux會話也就不存在了)安裝tmux-continuum插件解決tmux會話不能保存的問題。
-
tmux-continuum插件要求tmux版本為1.9以上,目前CentOS 7 上的版本為1.8。 所以,需要我們去github的tmux項目中下載新版本的 tmux替換系統中已有的老版本。
-
下載並安裝tmux插件 git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
- 編輯 ~/.tmux.conf文件,並在最后追加如下內容
# Edit ~/.tmux.conf and added lines below at the bottom set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-sensible' set -g @plugin 'tmux-plugins/tmux-resurrect' set -g @plugin 'tmux-plugins/tmux-continuum' set -g @continuum-restore 'on' # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) run '~/.tmux/plugins/tpm/tpm'
- 執行 tmux new -s test 創建一個臨時的session,然后在session中執行 ctrl-a I 組合鍵安裝tmux-continuum。安裝完成后ctrl-d結束當前session。至此continuum插件安裝完成。
參考資料:https://github.com/tmux/tmux https://github.com/tmux-plugins/tpm https://github.com/tmux-plugins/tmux-continuum
五、總結
nohup一般作為啟動服務或者守護進程來執行一個單獨的命令的情形下使用(
記得輸出重定向);screen和tmux可以作為日常連接遠程開發服務器做開發使用,可以方便的切換各種工作台,而不用打開多個終端。