本文首發於CSDN網站,下面的版本又通過進一步的修訂。前端
全文共12k字,閱讀需20分鐘。node
我一直信奉簡潔至上的原則,桌面窗口的數量越少,個人心情就越愉悅,開發的效率也就越高。反之,雜亂的桌面,暴漲的Chrome tab數量,或是無數的終端窗口,它們會逐步侵佔個人注意力,分散個人思惟,最終令我難以專一。所以桌面上我不多放文件,使用Chrome時常點 OneTab 回收標籤頁,切進終端時使用tmux管理窗口。python
我很懶,懶到指望開機後不須要任何操做,本地的十幾種web開發服務器就自動運行,固然我不但願連續彈出十幾個窗口或是tab,我須要的是靜默無感知的啓用服務,而後還能快速地進入到現場進行操做,web服務器運行時不佔據終端窗口,關閉iTem2後操做現場不會被銷燬。個人這些指望,tmux都能幫我實現,實際上,除了這些,tmux還能作得更多更好。git
到目前爲止,tmux幫助我兩年有餘,它帶給我許多驚喜。獨樂不如衆樂,願你也能一同享受tmux帶來的快樂。程序員
tmux是一款優秀的終端複用軟件,它比Screen更增強大,至於如何強大,網上有大量的文章討論了這點,本文再也不重複。tmux之因此受人們喜好,主要得益於如下三處功能:github
以上,只是主要功能,更多功能還在後頭,接下來我將詳細地介紹tmux的使用技巧。web
首先安裝之。chrome
在Mac中安裝:shell
# 先安裝Homebrew,有則跳過
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# 安裝tmux
brew install tmux複製代碼
在Linux中安裝:npm
sudo apt-get install tmux複製代碼
開始以前,咱們先了解下基本概念:
tmux採用C/S模型構建,輸入tmux命令就至關於開啓了一個服務器,此時默認將新建一個會話,而後會話中默認新建一個窗口,窗口中默認新建一個面板。會話、窗口、面板之間的聯繫以下:
一個tmux session
(會話)能夠包含多個window
(窗口),窗口默認充滿會話界面,所以這些窗口中能夠運行相關性不大的任務。
一個window
又能夠包含多個pane
(面板),窗口下的面板,都處於同一界面下,這些面板適合運行相關性高的任務,以便同時觀察到它們的運行狀況。
新建一個tmux session很是簡單,語法爲tmux new -s session-name
,也能夠簡寫爲tmux
,爲了方便管理,建議指定會話名稱,以下。
tmux # 新建一個無名稱的會話
tmux new -s demo # 新建一個名稱爲demo的會話複製代碼
會話中操做了一段時間,我但願斷開會話同時下次還能接着用,怎麼作?此時可使用detach命令。
tmux detach # 斷開當前會話,會話在後臺運行複製代碼
也許你以爲這個太麻煩了,是的,tmux的會話中,咱們已經可使用tmux快捷鍵了。使用快捷鍵組合Ctrl+b
+ d
,三次按鍵就能夠斷開當前會話。
斷開會話後,想要接着上次留下的現場繼續工做,就要使用到tmux的attach命令了,語法爲tmux attach-session -t session-name
,可簡寫爲tmux a -t session-name
或 tmux a
。一般咱們使用以下兩種方式之一便可:
tmux a # 默認進入第一個會話
tmux a -t demo # 進入到名稱爲demo的會話複製代碼
會話的使命完成後,必定是要關閉的。咱們可使用tmux的kill命令,kill命令有kill-pane
、kill-server
、kill-session
和 kill-window
共四種,其中kill-session
的語法爲tmux kill-session -t session-name
。以下:
tmux kill-session -t demo # 關閉demo會話
tmux kill-server # 關閉服務器,全部的會話都將關閉複製代碼
管理會話的第一步就是要查看全部的會話,咱們可使用以下命令:
tmux list-session # 查看全部會話
tmux ls # 查看全部會話,提倡使用簡寫形式複製代碼
若是恰好處於會話中怎麼辦?別擔憂,咱們可使用對應的tmux快捷鍵Ctrl+b
+ s
,此時tmux將打開一個會話列表,按上下鍵(⬆︎⬇︎)或者鼠標滾輪,可選中目標會話,按左右鍵(⬅︎➜)可收起或展開會話的窗口,選中目標會話或窗口後,按回車鍵便可完成切換。
關於快捷指令,首先要認識到的是:tmux的全部指令,都包含同一個前綴,默認爲Ctrl+b
,輸入完前綴事後,控制檯激活,命令按鍵才能生效。前面tmux會話相關的操做中,咱們共用到了兩個快捷鍵Ctrl+b
+ d
、Ctrl+b
+ s
,但這僅僅是冰山一角,欲窺tmux龐大的快捷鍵體系,請看下錶。
表一:系統指令。
前綴 | 指令 | 描述 |
---|---|---|
Ctrl+b |
? |
顯示快捷鍵幫助文檔 |
Ctrl+b |
d |
斷開當前會話 |
Ctrl+b |
D |
選擇要斷開的會話 |
Ctrl+b |
Ctrl+z |
掛起當前會話 |
Ctrl+b |
r |
強制重載當前會話 |
Ctrl+b |
s |
顯示會話列表用於選擇並切換 |
Ctrl+b |
: |
進入命令行模式,此時可直接輸入ls 等命令 |
Ctrl+b |
[ |
進入複製模式,按q 退出 |
Ctrl+b |
] |
粘貼複製模式中複製的文本 |
Ctrl+b |
~ |
列出提示信息緩存 |
表二:窗口(window)指令。
前綴 | 指令 | 描述 |
---|---|---|
Ctrl+b |
c |
新建窗口 |
Ctrl+b |
& |
關閉當前窗口(關閉前需輸入y or n 確認) |
Ctrl+b |
0~9 |
切換到指定窗口 |
Ctrl+b |
p |
切換到上一窗口 |
Ctrl+b |
n |
切換到下一窗口 |
Ctrl+b |
w |
打開窗口列表,用於且切換窗口 |
Ctrl+b |
, |
重命名當前窗口 |
Ctrl+b |
. |
修改當前窗口編號(適用於窗口從新排序) |
Ctrl+b |
f |
快速定位到窗口(輸入關鍵字匹配窗口名稱) |
表三:面板(pane)指令。
前綴 | 指令 | 描述 |
---|---|---|
Ctrl+b |
" |
當前面板上下一分爲二,下側新建面板 |
Ctrl+b |
% |
當前面板左右一分爲二,右側新建面板 |
Ctrl+b |
x |
關閉當前面板(關閉前需輸入y or n 確認) |
Ctrl+b |
z |
最大化當前面板,再重複一次按鍵後恢復正常(v1.8版本新增) |
Ctrl+b |
! |
將當前面板移動到新的窗口打開(原窗口中存在兩個及以上面板有效) |
Ctrl+b |
; |
切換到最後一次使用的面板 |
Ctrl+b |
q |
顯示面板編號,在編號消失前輸入對應的數字可切換到相應的面板 |
Ctrl+b |
{ |
向前置換當前面板 |
Ctrl+b |
} |
向後置換當前面板 |
Ctrl+b |
Ctrl+o |
順時針旋轉當前窗口中的全部面板 |
Ctrl+b |
方向鍵 |
移動光標切換面板 |
Ctrl+b |
o |
選擇下一面板 |
Ctrl+b |
空格鍵 |
在自帶的面板佈局中循環切換 |
Ctrl+b |
Alt+方向鍵 |
以5個單元格爲單位調整當前面板邊緣 |
Ctrl+b |
Ctrl+方向鍵 |
以1個單元格爲單位調整當前面板邊緣(Mac下被系統快捷鍵覆蓋) |
Ctrl+b |
t |
顯示時鐘 |
tmux的絲滑分屏功能正是得益於以上系統、窗口、面板的快捷指令,只要你願意,你就能夠解除任意的快捷指令,而後綁上你喜歡的指令,固然這就涉及到它的可配置性了,請繼續往下讀。
除了快捷指令外,tmux還提供了相似vim的配置性功能。可配置性是軟件的一項進階級功能,只有具有了可配置性,軟件纔有了鮮活的個性,用戶才能體會到操做的快感。
相信只要你用過幾回tmux,就會發現Ctrl+b
指令前綴,着實不太方便。這兩個鍵相距太遠,按鍵成本過高了。所以咱們首先須要將它更換爲距離更近的Ctrl+a
組合鍵,或者不經常使用的 ` 鍵(固然其餘鍵也是能夠的)。
tmux的用戶級配置文件爲~/.tmux.conf
(沒有的話就建立一個),修改快捷指令,只須要增長以下三行便可。
set -g prefix C-a #
unbind C-b # C-b即Ctrl+b鍵,unbind意味着解除綁定
bind C-a send-prefix # 綁定Ctrl+a爲新的指令前綴
# 從tmux v1.6版起,支持設置第二個指令前綴
set-option -g prefix2 ` # 設置一個不經常使用的`鍵做爲指令前綴,按鍵更快些複製代碼
修改的~/.tmux.conf
配置文件有以下兩種方式能夠令其生效:
Ctrl+b
指令前綴,而後按下系統指令:
,進入到命令模式後輸入source-file ~/.tmux.conf
,回車後生效。既然快捷指令如此方便,更爲優雅的作法是新增一個加載配置文件的快捷指令 ,這樣就能夠隨時隨地load新的配置了,以下所示。
# 綁定快捷鍵爲r
bind r source-file ~/.tmux.conf \; display-message "Config reloaded.."複製代碼
請特別注意,在已經建立的窗口中,即便加載了新的配置,舊的配置依然有效(只要你新加的功能沒有覆蓋舊的配置,所以若是你第一次綁定快捷指令爲x
鍵,而後又改成綁定y
鍵,那麼x
和y
都將有效),新建會話不受此影響,將直接採用新的配置。
既然咱們已經邁出配置化的第一步,那麼接下來咱們能夠作得更多。
tmux中,使用最多的功能之一就是新增一個面板。水平方向新增面板的指令是 prefix
+ "
,垂直方向是 prefix
+ %
,"
和 %
須要兩個鍵同時按下才能完成,加上指令前綴至少須要3~4次按鍵才能組成一個完整的指令,同時這個兩個鍵也不夠醒目和方便,所以咱們能夠綁定兩個更經常使用的指令 -
、|
,以下所示:
unbind '"'
bind - splitw -v -c '#{pane_current_path}' # 垂直方向新增面板,默認進入當前目錄
unbind %
bind | splitw -h -c '#{pane_current_path}' # 水平方向新增面板,默認進入當前目錄複製代碼
默認狀況下,tmux的多窗口之間的切換以及面板大小調整,須要輸入指令才能完成,這一過程,涉及到的指令較多,並且操做麻煩,特別是面板大小調整,指令難以一步到位,這個時候開啓鼠標支持就完美了。
對於tmux v2.1(2015.10.28)以前的版本,需加入以下配置:
setw -g mode-mouse on # 支持鼠標選取文本等
setw -g mouse-resize-pane on # 支持鼠標拖動調整面板的大小(經過拖動面板間的分割線)
setw -g mouse-select-pane on # 支持鼠標選中並切換面板
setw -g mouse-select-window on # 支持鼠標選中並切換窗口(經過點擊狀態欄窗口名稱)複製代碼
有的地方可能會出現set-window-option
的寫法,setw
就是它的別名。
對於tmux v2.1及以上的版本,僅需加入以下配置:
set-option -g mouse on # 等同於以上4個指令的效果複製代碼
須要注意的是,開啓鼠標支持後,iTem2默認的鼠標選中即複製功能須要同時按下 Alt
鍵,纔會生效。
鼠標支持確實能帶來很大的便捷性,特別是對於習慣了鼠標操做的tmux新手,但對於鍵盤愛好者而言,這不是什麼好消息,對他們而言,雙手不離鍵盤是基本素質。
雖然指令前綴加方向鍵
能夠切換面板,但方向鍵
太遠,不夠快,不夠Geek。不要緊,咱們能夠將面板切換升級爲熟悉的h
、j
、k
、l
鍵位。
# 綁定hjkl鍵爲面板切換的上下左右鍵
bind -r k select-pane -U # 綁定k爲↑
bind -r j select-pane -D # 綁定j爲↓
bind -r h select-pane -L # 綁定h爲←
bind -r l select-pane -R # 綁定l爲→複製代碼
-r
表示可重複按鍵,大概500ms以內,重複的h
、j
、k
、l
按鍵都將有效,完美支持了快速切換的Geek需求。
除了上下左右外, 還有幾個快捷指令能夠設置。
bind -r e lastp # 選擇最後一個面板
bind -r ^e last # 選擇最後一個窗口
bind -r ^u swapp -U # 與前一個面板交換位置
bind -r ^d swapp -D # 與後一個面板交換位置複製代碼
習慣了全鍵盤操做後,命令的便捷性不言而喻。既然面板切換的指令均可以升級,面板大小調整的指令天然也不能落後。以下配置就能夠升級你的操做:
# 綁定Ctrl+hjkl鍵爲面板上下左右調整邊緣的快捷指令
bind -r ^k resizep -U 10 # 綁定Ctrl+k爲往↑調整面板邊緣10個單元格
bind -r ^j resizep -D 10 # 綁定Ctrl+j爲往↓調整面板邊緣10個單元格
bind -r ^h resizep -L 10 # 綁定Ctrl+h爲往←調整面板邊緣10個單元格
bind -r ^l resizep -R 10 # 綁定Ctrl+l爲往→調整面板邊緣10個單元格複製代碼
以上,resizep
即resize-pane
的別名。
當窗口中面板的數量逐漸增多時,每一個面板的空間就會逐漸減小。爲了保證有足夠的空間顯示內容,tmux從v1.8版本起,提供了面板的最大化功能,輸入tmux-prefix+z
,就能夠最大化當前面板至窗口大小,只要再重複輸入一次,便恢復正常。那麼tmux v1.8如下的版本,怎麼辦呢?別急,有大神提供了以下的解決方案。
首先編寫一個zoom腳本,該腳本經過新建一個窗口,交換當前面板與新的窗口默認面板位置,來模擬最大的功能;經過重複一次按鍵,還原面板位置,並關閉新建的窗口,來模擬還原功能,以下所示:
#!/bin/bash -f
currentwindow=`tmux list-window | tr '\t' ' ' | sed -n -e '/(active)/s/^[^:]*: *\([^ ]*\) .*/\1/gp'`;
currentpane=`tmux list-panes | sed -n -e '/(active)/s/^\([^:]*\):.*/\1/gp'`;
panecount=`tmux list-panes | wc | sed -e 's/^ *//g' -e 's/ .*$//g'`;
inzoom=`echo $currentwindow | sed -n -e '/^zoom/p'`;
if [ $panecount -ne 1 ]; then
inzoom="";
fi
if [ $inzoom ]; then
lastpane=`echo $currentwindow | rev | cut -f 1 -d '@' | rev`;
lastwindow=`echo $currentwindow | cut -f 2- -d '@' | rev | cut -f 2- -d '@' | rev`;
tmux select-window -t $lastwindow;
tmux select-pane -t $lastpane;
tmux swap-pane -s $currentwindow;
tmux kill-window -t $currentwindow;
else
newwindowname=zoom@$currentwindow@$currentpane;
tmux new-window -d -n $newwindowname;
tmux swap-pane -s $newwindowname;
tmux select-window -t $newwindowname;
fi複製代碼
不妨將該腳本存放在~/.tmux
目錄中(沒有則新建目錄),接下來只須要綁定一個快捷指令就行,以下。
unbind z
bind z run ". ~/.tmux/zoom"複製代碼
經過上面的zoom腳本,面板能夠輕鬆地最大化爲一個新的窗口。那麼反過來,窗口是否是能夠最小化爲一個面板呢?
試想這樣一個場景:當你打開多個窗口後,而後想將其中幾個窗口合併到當前窗口中,以便對比觀察輸出。
實際上,你的要求就是將其它窗口變成面板,而後合併到當前窗口中。對於這種操做,咱們能夠在當前窗口,按下prefix
+ :
,打開命令行,而後輸入以下命令:
join-pane -s window01 # 合併名稱爲window01的窗口的默認(第一個)面板到當前窗口中
join-pane -s window01.1 # .1顯式指定了第一個面板,.2就是第二個面板(我本地將面板編號起始值設置爲1,默認是0)複製代碼
每次執行join-pane
命令都會合並一個面板,而且指定的窗口會減小一個面板,直到面板數量爲0,窗口關閉。
除了在當前會話中操做外,join-pane
命令甚至能夠從其它指定會話中合併面板,格式爲join-pane -s [session_name]:[window].[pane]
,如join-pane -s 2:1.1
即合併第二個會話的第一個窗口的第一個面板到當前窗口,當目標會話的窗口和麪板數量爲0時,會話便會關閉。
注:上一節中的swap-pane
命令與join-pane
語法基本一致。
bind m command-prompt "splitw -h 'exec man %%'" # 綁定m鍵爲在新的panel打開man
# 綁定P鍵爲開啓日誌功能,以下,面板的輸出日誌將存儲到桌面
bind P pipe-pane -o "cat >>~/Desktop/#W.log" \; display "Toggled logging to ~/Desktop/#W.log"複製代碼
tmux會話中,Mac的部分命令如 osascript
、open
、pbcopy
或 pbpaste
等可能會失效(失效命令未列全)。
部分bug列表以下:
對此,咱們能夠經過安裝reattach-to-user-namespace
包裝程序來解決這個問題。
brew install reattach-to-user-namespace複製代碼
在~/.tmux.conf
中添加配置:
set -g default-command "reattach-to-user-namespace -l $SHELL"複製代碼
這樣你的交互式shell最終可以從新鏈接到用戶級的命名空間。因爲鏈接狀態可以被子進程繼承,故以上配置保證了全部從 shell 啓動的命令可以被正確地鏈接。
有些時候,咱們可能會在不一樣的操做系統中共享配置文件,若是你的tmux版本大於1.9,咱們還可使用if-shell
來判斷是否Mac系統,而後再指定default-command
。
if-shell 'test "$(uname -s)" = Darwin' 'set-option -g default-command "exec reattach-to-user-namespace -l $SHELL"'複製代碼
對於tmux v1.8及更早的版本,可使用以下包裝後的配置:
set-option -g default-command 'command -v reattach-to-user-namespace >/dev/null && exec reattach-to-user-namespace -l "$SHELL" || exec "$SHELL"'複製代碼
以上,$SHELL
對應於你的默認Shell,一般是/usr/bin/bash
或 /usr/local/bin/zsh
。
tmux中操做文本,天然離不開復制模式,一般使用複製模式的步驟以下:
`+[
進入複製模式空格鍵
開始複製,移動光標選擇複製區域回車鍵
複製選中文本並退出複製模式`+]
粘貼文本查看複製模式默認的快捷鍵風格:
tmux show-window-options -g mode-keys # mode-keys emacs複製代碼
默認狀況下,快捷鍵爲emacs
風格。
爲了讓複製模式更加方便,咱們能夠將快捷鍵設置爲熟悉的vi
風格,以下:
setw -g mode-keys vi # 開啓vi風格後,支持vi的C-d、C-u、hjkl等快捷鍵複製代碼
除了快捷鍵外,複製模式的啓用、選擇、複製、粘貼等按鍵也能夠向vi
風格靠攏。
bind Escape copy-mode # 綁定esc鍵爲進入複製模式
bind -t vi-copy v begin-selection # 綁定v鍵爲開始選擇文本
bind -t vi-copy y copy-selection # 綁定y鍵爲複製選中文本
bind p pasteb # 綁定p鍵爲粘貼文本(p鍵默認用於進入上一個窗口,不建議覆蓋)複製代碼
以上,綁定 v
、y
兩鍵的設置只在tmux v2.4版本如下才有效,對於v2.4及以上的版本,綁定快捷鍵須要使用 -T
選項,發送指令須要使用 -X
選項,請參考以下設置:
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-selection-and-cancel複製代碼
tmux複製操做的內容默認會存進buffer
裏,buffer
是一個粘貼緩存區,新的緩存老是位於棧頂,它的操做命令以下:
tmux list-buffers # 展現全部的 buffers
tmux show-buffer [-b buffer-name] # 顯示指定的 buffer 內容
tmux choose-buffer # 進入 buffer 選擇頁面(支持jk上下移動選擇,回車選中並粘貼 buffer 內容到面板上)
tmux set-buffer # 設置buffer內容
tmux load-buffer [-b buffer-name] file-path # 從文件中加載文本到buffer緩存
tmux save-buffer [-a] [-b buffer-name] path # 保存tmux的buffer緩存到本地
tmux paste-buffer # 粘貼buffer內容到會話中
tmux delete-buffer [-b buffer-name] # 刪除指定名稱的buffer複製代碼
以上buffer操做在不指定buffer-name時,默認處理是棧頂的buffer緩存。
在tmux會話的命令行輸入時,能夠省略上述tmux前綴,其中list-buffers的操做以下所示:
choose-buffer的操做以下所示:
默認狀況下,buffers內容是獨立於系統粘貼板的,它存在於tmux進程中,且能夠在會話間共享。
存在於tmux進程中的buffer緩存,雖然能夠在會話間共享,但不能直接與系統粘貼板共享,難免有些遺憾。幸運的是,如今咱們有成熟的方案來實現這個功能。
在Linux上使用粘貼板
一般,Linux中可使用xclip
工具來接入系統粘貼板。
首先,須要安裝xclip
。
sudo apt-get install xclip複製代碼
而後,.tmux.conf
的配置以下。
# buffer緩存複製到Linux系統粘貼板
bind C-c run " tmux save-buffer - | xclip -i -sel clipboard"
# Linux系統粘貼板內容複製到會話
bind C-v run " tmux set-buffer \"$(xclip -o -sel clipboard)\"; tmux paste-buffer"複製代碼
按下prefix
+ Ctrl
+ c
鍵,buffer緩存的內容將經過xlip
程序複製到粘貼板,按下prefix
+ Ctrl
+ v
鍵,tmux將經過xclip
訪問粘貼板,而後由set-buffer命令設置給buffer緩存,最後由paste-buffer粘貼到tmux會話中。
在Mac上使用粘貼板
咱們都知道,Mac自帶 pbcopy
和 pbpaste
命令,分別用於複製和粘貼,但在tmux命令中它們卻不能正常運行。這裏我將詳細介紹下緣由:
Mac的粘貼板服務是在引導命名空間註冊的。命名空間存在層次之分,更高級別的命名空間擁有訪問低級別命名空間(如root引導命名空間)的權限,反之卻不行。流程建立的屬於Mac登陸會話的一部分,它會被自動包含在用戶級的引導命名空間中,所以只有用戶級的命名空間才能訪問粘貼板服務。tmux使用守護進程(3)庫函數建立其服務器進程,在Mac OS X 10.5中,蘋果改變了守護進程(3)的策略,將生成的過程從最初的引導命名空間移到了根引導命名空間。而根引導命名空間訪問權限較低,這意味着tmux服務器,和它的子進程,一同失去了原引導命名空間的訪問權限(即無權限訪問粘貼板服務)。
如此,咱們可使用一個小小的包裝程序來從新鏈接到合適的命名空間,而後執行訪問用戶級命名空間的粘貼板服務,這個包裝程序就是reattach-to-user-namespace
。
那麼,Mac下.tmux.conf
的配置以下:
# buffer緩存複製到Mac系統粘貼板
bind C-c run "tmux save-buffer - | reattach-to-user-namespace pbcopy"
# Mac系統粘貼板內容複製到會話
bind C-v run "reattach-to-user-namespace pbpaste | tmux load-buffer - \; paste-buffer -d"複製代碼
reattach-to-user-namespace
做爲包裝程序來訪問Mac粘貼板,按下prefix
+ Ctrl
+ c
鍵,buffer緩存的內容將複製到粘貼板,按下prefix
+ Ctrl
+ v
鍵,粘貼板的內容將經過 load-buffer 加載,而後由 paste-buffer 粘貼到tmux會話中。
爲了在複製模式中使用Mac系統的粘貼板,可作以下配置:
# 綁定y鍵爲複製選中文本到Mac系統粘貼板
bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel 'reattach-to-user-namespace pbcopy'
# 鼠標拖動選中文本,並複製到Mac系統粘貼板
bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel "pbcopy"複製代碼
完成以上配置後記得重啓tmux服務器。至此,複製模式中,按y
鍵將保存選中的文本到Mac系統粘貼板,隨後按Command
+ v
鍵即可粘貼。
信息時代,數據尤其重要。tmux保護現場的能力依賴於tmux進程,若是進程退出,則意味着會話數據的丟失,所以關機重啓後,tmux中的會話將被清空,這不是咱們想要見到的。幸運的是,目前有這樣兩款插件:Tmux Resurrect
和 Tmux Continuum
,能夠永久保存tmux會話(它們均適用於tmux v1.9及以上版本)。
Tmux Resurrect無須任何配置,就可以備份tmux會話中的各類細節,包括窗口、面板的順序、佈局、工做目錄,運行程序等等數據。所以它能在系統重啓後徹底地恢復會話。因爲其冪等的恢復機制,它不會試圖去恢復一個已經存在的窗口或者面板,因此,即便你不當心多恢復了幾回會話,它也不會出現問題,這樣主動恢復時咱們就沒必要擔憂手抖多按了一次。另外,若是你是tmuxinator用戶,我也建議你遷移到 tmux-resurrect插件上來,具體請參考Migrating from tmuxinator
。
Tmux Resurrec安裝過程以下所示:
cd ~/.tmux
mkdir plugins
git clone https://github.com/tmux-plugins/tmux-resurrect.git複製代碼
安裝後需在~/.tmux.conf
中增長一行配置:
run-shell ~/.tmux/plugins/tmux-resurrect/resurrect.tmux複製代碼
至此安裝成功,按下prefix + r
重載tmux配置。
Tmux Resurrec提供以下兩個操做:
prefix
+ Ctrl + s
,tmux狀態欄在保存開始,保存後分別提示"Saving...","Tmux environment saved !"。prefix
+ Ctrl + r
,tmux狀態欄在恢復開始,恢復後分別提示"Restoring...","Tmux restore complete !"。保存時,tmux會話的詳細信息會以文本文件的格式保存到~/.tmux/resurrect
目錄,恢復時則今後處讀取,因爲數據文件是明文的,所以你徹底能夠自由管理或者編輯這些會話狀態文件(若是備份頻繁,記得按期清除歷史備份)。
可選的配置
Tmux Resurrec自己是免配置開箱即用的,但同時也提供了以下選項以便修改其默認設置。
set -g @resurrect-save 'S' # 修改保存指令爲S
set -g @resurrect-restore 'R' 修改恢復指令爲R
# 修改會話數據的保持路徑,此處不能使用除了$HOME, $HOSTNAME, ~以外的環境變量
set -g @resurrect-dir '/some/path'複製代碼
默認狀況下只有一個保守的列表項(即vi vim nvim emacs man less more tail top htop irssi mutt
)能夠恢復,對此 Restoring programs doc 解釋了怎麼去恢復額外的項目。
進階的備份
除了基礎備份外,Tmux Resurrec還提供進階的備份功能,以下所示:
進階的備份功能默認不開啓,須要特別配置。
1)恢復vim 和 neovim 會話,須要完成以下兩步:
經過vim的vim-obsession插件保存vim/neovim會話。
cd ~/.vim/bundle
git clone git://github.com/tpope/vim-obsession.git
vim -u NONE -c "helptags vim-obsession/doc" -c q複製代碼
在~/.tmux.conf
中增長兩行配置:
set -g @resurrect-strategy-vim 'session' # for vim
set -g @resurrect-strategy-nvim 'session' # for neovim複製代碼
2)恢復面板內容,需在~/.tmux.conf
中增長一行配置:
set -g @resurrect-capture-pane-contents 'on' # 開啓恢復面板內容功能複製代碼
目前使用該功能時,請確保tmux的default-command
沒有包含&&
或者||
操做符,不然將致使bug。(查看default-command
的值,請使用命令tmux show -g default-command
。)
3)恢復shell的歷史記錄,需在~/.tmux.conf
中增長一行配置:
set -g @resurrect-save-shell-history 'on'複製代碼
因爲技術的限制,保存時,只有無前臺任務運行的面板,它的shell歷史記錄才能被保存。
可能你嫌手動保存和恢復太過麻煩,別擔憂,這不是問題。Tmux Continuum 在 Tmux Resurrec的基礎上更進一步,如今保存和恢復所有自動化了,如你所願,能夠無感使用tmux,不用再擔憂備份問題。
Tmux Continuum安裝過程以下所示(它依賴Tmux Resurrect,請保證已安裝Tmux Resurrect插件):
cd ~/.tmux/plugins
git clone https://github.com/tmux-plugins/tmux-continuum.git複製代碼
安裝後需在~/.tmux.conf
中增長一行配置:
run-shell ~/.tmux/plugins/tmux-continuum/continuum.tmux複製代碼
Tmux Continuum默認每隔15mins備份一次,我設置的是一天一次:
set -g @continuum-save-interval '1440'複製代碼
關閉自動備份,只需設置時間間隔爲 0
便可:
set -g @continuum-save-interval '0'複製代碼
想要在tmux啓動時就恢復最後一次保存的會話環境,需增長以下配置:
set -g @continuum-restore 'on' # 啓用自動恢復複製代碼
若是不想要啓動時自動恢復的功能了,直接移除上面這行就行。想要絕對肯定自動恢復不會發生,就在用戶根目錄下建立一個tmux_no_auto_restore
空文件(建立命令:touch ~/tmux_no_auto_restore
),該文件存在時,自動恢復將不觸發。
對於tmux高級用戶(可能就是你)而言,同時運行多個tmux服務器也是有可能的。你可能並不但願後面啓用的幾個tmux服務器自動恢復或者自動保存會話。所以Tmux Continuum會優先在第一個啓用的tmux服務器中生效,隨後啓用的tmux服務器再也不享受自動恢復或自動保存會話的待遇。
實際上,無論Tmux Continuum功能有沒有啓用,或者多久保存一次,咱們都有辦法從狀態欄知曉。Tmux Continuum提供了一個查看運行狀態的插值#{continuum_status}
,它支持status-right
和 status-left
兩種狀態欄設置,以下所示:
set -g status-right 'Continuum status: #{continuum_status}'複製代碼
tmux運行時,#{continuum_status}
將顯示保存的時間間隔(單位爲分鐘),此時狀態欄會顯示:
Continuum status: 1440複製代碼
若是其自動保存功能關閉了,那麼狀態欄會顯示:
Continuum status: off複製代碼
藉助Tmux Continuum插件,Mac重啓時,咱們甚至能夠選擇在Terminal
或者 iTerm2
中自動全屏啓用tmux。
爲此,需在~/.tmux.conf
中增長一行配置:
set -g @continuum-boot 'on'複製代碼
Mac下,自動啓用tmux還支持以下選項:
set -g @continuum-boot-options 'fullscreen'
,Terminal
自動全屏,tmux命令在Terminal
中執行。set -g @continuum-boot-options 'iterm'
, iTerm2
替換 Terminal
應用,tmux命令在iTerm2
中執行。set -g @continuum-boot-options 'iterm,fullscreen'
,iTerm2
自動全屏,tmux命令在iTerm2
中執行。Linux中則沒有這些選項,它只能設置爲自動啓用tmux服務器。
以上,咱們直接安裝了tmux插件。這沒有問題,可當插件愈來愈多時,咱們就會須要統一的插件管理器。所以官方提供了tpm(支持tmux v1.9及以上版本)。
tpm安裝過程以下所示:
cd ~/.tmux/plugins
git clone https://github.com/tmux-plugins/tpm複製代碼
安裝後需在~/.tmux.conf
中增長以下配置:
# 默認須要引入的插件
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
# 引入其餘插件的示例
# set -g @plugin 'github_username/plugin_name' # 格式:github用戶名/插件名
# set -g @plugin 'git@github.com/user/plugin' # 格式:git@github插件地址
# 初始化tmux插件管理器(保證這行在~/.tmux.conf的很是靠後的位置)
run '~/.tmux/plugins/tpm/tpm'複製代碼
而後按下prefix + r
重載tmux配置,使得tpm生效。
基於tpm插件管理器,安裝插件僅需以下兩步:
~/.tmux.conf
中增長新的插件,如set -g @plugin '...'
。prefix
+ I
鍵下載插件,並刷新tmux環境。更新插件,請按下prefix
+ U
鍵,選擇待更新的插件後,回車確認並更新。
卸載插件,需以下兩步:
~/.tmux.conf
中移除插件所在行。prefix
+ alt
+ u
移除插件。tmux多會話鏈接實時同步的功能,使得結對編程成爲了可能,這也是開發者最喜歡的功能之一。如今就差一步了,就是藉助tmate把tmux會話分享出去。
tmate是tmux的管理工具,它能夠輕鬆的建立tmux會話,而且自動生成ssh連接。
安裝tmate
brew install tmate複製代碼
使用tmate新建一個tmux會話
tmate複製代碼
此時屏幕下方會顯示ssh url,以下所示:
查看tmate生成的ssh連接
tmate show-messages複製代碼
生成的ssh url以下所示,其中一個爲只讀,另外一個可編輯。
使用tmate遠程共享tmux會話,受制於多方的網絡質量,必然會存在些許延遲。若是共享會話的多方擁有同一個遠程服務器的帳號,那麼咱們可使用組會話
解決這個問題。
先在遠程服務器上新建一個公共會話,命名爲groupSession
。
tmux new -s groupSession複製代碼
其餘用戶不去直接鏈接這個會話,而是經過建立一個新的會話來加入上面的公共會話groupSession
。
tmux new -t groupSession -s otherSession複製代碼
此時兩個用戶均可以在同一個會話裏操做,就會好像第二個用戶鏈接到了groupSession
的會話同樣。此時兩個用戶均可以建立新建的窗口,新窗口的內容依然會實時同步,可是其中一個用戶切換到其它窗口,對另一個用戶沒有任何影響,所以在這個共享的組會話中,用戶各自的操做能夠經過新建窗口來執行。即便第二個用戶關閉otherSession
會話,共享會話groupSession
依然存在。
組會話在共享的同時,又保留了相對的獨立,很是適合結對編程場景,它是結對編程最簡單的方式,若是帳號不能共享,咱們就要使用下面的方案了。
開始以前咱們須要確保用戶對遠程服務器上同一個目錄擁有相同的讀寫權限,假設這個目錄爲/var/tmux/
。
使用new-session(簡寫new)建立會話時,使用的是默認的socket位置,默認socket沒法操做,因此咱們須要建立一個指定socket文件的會話。
tmux -S /var/tmux/sharefile複製代碼
另外一個用戶進入時,須要指定socket文件加入會話。
tmux -S /var/tmux/sharefile attach複製代碼
這樣,兩個不一樣的用戶就能夠共享同一個會話了。
一般狀況下,不一樣的用戶使用不一樣的配置文件來建立會話,可是,使用指定socket文件建立的tmux會話,會話加載的是第一個建立會話的用戶的~/.tmux.conf
配置文件,隨後加入會話的其餘用戶,依然使用同一份配置文件。
要想tmux更加人性化、性能更佳,不妨參考下以下配置。
set -g base-index 1 # 設置窗口的起始下標爲1
set -g pane-base-index 1 # 設置面板的起始下標爲1複製代碼
set -g status-utf8 on # 狀態欄支持utf8
set -g status-interval 1 # 狀態欄刷新時間
set -g status-justify left # 狀態欄列表左對齊
setw -g monitor-activity on # 非當前窗口有內容更新時在狀態欄通知
set -g status-bg black # 設置狀態欄背景黑色
set -g status-fg yellow # 設置狀態欄前景黃色
set -g status-style "bg=black, fg=yellow" # 狀態欄前景背景色
set -g status-left "#[bg=#FF661D] ❐ #S " # 狀態欄左側內容
set -g status-right 'Continuum status: #{continuum_status}' # 狀態欄右側內容
set -g status-left-length 300 # 狀態欄左邊長度300
set -g status-right-length 500 # 狀態欄左邊長度500
set -wg window-status-format " #I #W " # 狀態欄窗口名稱格式
set -wg window-status-current-format " #I:#W#F " # 狀態欄當前窗口名稱格式(#I:序號,#w:窗口名稱,#F:間隔符)
set -wg window-status-separator "" # 狀態欄窗口名稱之間的間隔
set -wg window-status-current-style "bg=red" # 狀態欄當前窗口名稱的樣式
set -wg window-status-last-style "fg=red" # 狀態欄最後一個窗口名稱的樣式
set -g message-style "bg=#202529, fg=#91A8BA" # 指定消息通知的前景、後景色複製代碼
默認狀況下,tmux中使用vim編輯器,文本內容的配色和直接使用vim時有些差距,此時須要開啓256 colors的支持,配置以下。
set -g default-terminal "screen-256color"複製代碼
或者:
set -g default-terminal "tmux-256color"複製代碼
或者啓動tmux時增長參數-2
:
alias tmux='tmux -2' # Force tmux to assume the terminal supports 256 colours複製代碼
tmux默認會自動重命名窗口,頻繁的命令行操做,將頻繁觸發重命名,比較浪費CPU性能,性能差的計算機上,問題可能更爲明顯。建議添加以下配置關閉rename機制。
setw -g automatic-rename off
setw -g allow-rename off複製代碼
tmux默認會同步同一個會話的操做到全部會話鏈接的終端窗口中,這種同步機制,限制了窗口的大小爲最小的會話鏈接。所以當你開一個大窗口去鏈接會話時,實際的窗口將自動調整爲最小的那個會話鏈接的窗口,終端剩餘的空間將填充排列整齊的小圓點,以下所示。
爲了不這種問題,咱們能夠在鏈接會話的時候,斷開其餘的會話鏈接。
tmux a -d複製代碼
若是已經進入了tmux會話中,才發現這種問題,這個時候能夠輸入命令達到一樣的效果。
`: a -d複製代碼
tmux做爲終端複用軟件,支持純命令行操做也是其一大亮點。你既能夠啓用可視化界面建立會話,也能夠運行腳本生成會話,對於tmux依賴者而言,編寫幾個tmux腳本批量維護會話列表,快速重啓、切換、甚至分享部分會話都是很是方便的。可能會有人說爲何不用Tmux Resurrect呢?是的,Tmux Resurrect很好,一鍵恢復也很誘人,可是對於一個維護大量tmux會話的用戶而言,一鍵恢復可能不見得好,分批次恢復多是他(她)更想要的,腳本化的tmux就很好地知足了這點。
腳本中建立tmux會話時,因爲不須要開啓可視化界面,須要輸入-d
參數指定會話後臺運行,以下。
tmux new -s init -d # 後臺建立一個名稱爲init的會話複製代碼
新建的會話,建議重命令會話的窗口名稱,以便後續維護。
# 重命名init會話的第一個窗口名稱爲service
tmux rename-window -t "init:1" service複製代碼
如今,能夠在剛纔的窗口中輸入指令了。
# 切換到指定目錄並運行python服務
tmux send -t "init:service" "cd ~/workspace/language/python/;python2.7 server.py" Enter複製代碼
一個面板佔用一個窗口可能太浪費了,咱們來分個屏吧。
# 默認上下分屏
tmux split-window -t "init:service"
# 切換到指定目錄並運行node服務
tmux send -t "init:service" 'cd ~/data/louiszhai/node-webserver/;npm start' Enter複製代碼
如今一個窗口擁有上下兩個面板,是時候建立一個新的窗口來運行更多的程序了。
# 新建一個名稱爲tool的窗口
tmux neww -a -n tool -t init # neww等同於new window
# 運行weinre調試工具
tmux send -t "init:tool" "weinre --httpPort 8881 --boundHost -all-" Enter複製代碼
另外新建窗口運行程序,有更方便的方式,好比使用 processes
選項。
tmux neww-n processes ls # 新建窗口並執行命令,命令執行結束後窗口將關閉
tmux neww-n processes top # 因爲top命令持續在前臺運行,所以窗口將保留,直到top命令退出複製代碼
新的窗口,咱們嘗試下水平分屏。
# 水平分屏
tmux split-window -h -t "init:tool"
# 切換到指定目錄並啓用aria2 web管理後臺
tmux send -t "init:tool" "cd ~/data/tools/AriaNg/dist/;python -m SimpleHTTPServer 10108" Enter複製代碼
相似的腳本,咱們能夠編寫一打,這樣快速重啓、切換、甚至分享會話都將更加便捷。
開機自動準備工做環境是一個很好的idea,但卻很差實現。對於程序員而言,一個開機即用的計算機會節省大量的初始化操做,特別是前端工程師,本地經常會啓用多個服務器,每次開機挨個啓動將耗時耗力。爲此,在遇到tmux以前,我經常拖延重啓計算機的時機,一度連續運行Mac一月之久,直到它不堪重負。
有了tmux腳本化的基礎,開機自動啓用web服務器就不在話下了,接杯水的時間,計算機就重啓恢復了滿血。以下是操做步驟:
首先,上面的tmux腳本,能夠合併到同一個文件中,指定文件權限爲可執行,並命名爲init.sh
(名稱可自取)。
chmod u+x ./init.sh複製代碼
而後,打開 系統偏好設置
- 用戶與羣組
- 登陸項
,點擊添加按鈕+
,選擇剛剛保存的init.sh
腳本,最終效果以下:
至此,Mac開機將自動運行 init.sh
腳本,自動啓用web服務器。
完成了上面這些配置,就真正實現了一鍵開機。
最後,附上我本地的配置文件 .tmux.conf,以及啓動腳本 init.sh。
版權聲明:轉載需註明做者和出處。
本文做者: louis
本文連接: louiszhai.github.io/2017/09/30/…
相關文章