第6章 工作流

2018-02-24 15:48 更新

第 6 章 工作流

就 tmux 自身來說,它只是一個(gè)添加了一些附加功能的另一個(gè)終端而已,只是顯示了更多的終端會(huì)話。但是 tmux 讓我們在這些會(huì)話里運(yùn)行程序時(shí)更加方便,所以本章將會(huì)探討一些常見、不常見的配置和命令,它們可能對你的日常工作有很大的幫助。你會(huì)學(xué)到管理面板和會(huì)話的高級方式,如何讓 tmux 和 shell 一起工作,如何使用外部腳本擴(kuò)展 tmux 命令,如何創(chuàng)建能執(zhí)行數(shù)條命令的快捷鍵。我們先從管理窗口和面板開始。

6.1 高效使用面板和窗口工作

在本書中,你已經(jīng)見到數(shù)種方式把 tmux 會(huì)話分割為多個(gè)面板和窗口。在本節(jié),我們會(huì)學(xué)習(xí)使用面板和窗口工作的幾種高級方式。

把面板變?yōu)榇翱?/h3>

面板很適合用來劃分工作空間,但是有時(shí)我們需要把一個(gè)面板“彈出(pop out)”變?yōu)橐粋€(gè)獨(dú)立的窗口,這樣看這部分內(nèi)容就會(huì)更方便。tmux 有這樣一個(gè)命令來實(shí)現(xiàn)這個(gè)功能。
在任意面板內(nèi),按下 PREFIX ! 鍵,tmux 就會(huì)依據(jù)當(dāng)前面板創(chuàng)建一個(gè)新的窗口。

把窗口變?yōu)槊姘?/h3>

有時(shí)候,我們需要合并一個(gè)工作空間,我們可以很簡便地把窗口變?yōu)橐粋€(gè)面板。為此,我們要提一下 join-pane 命令。

在“合并(join)”一個(gè)面板時(shí),我們有可能把面板從一個(gè)會(huì)話移動(dòng)到另一個(gè)會(huì)話里。此時(shí)需要指定源窗口和面板,后面跟隨目標(biāo)窗口和面板。如果不指定目標(biāo)窗口,那么當(dāng)前焦點(diǎn)窗口就會(huì)作為目標(biāo)窗口。

下面我們通過創(chuàng)建一個(gè)帶有兩個(gè)窗口的 tmux 會(huì)話來演示:

$ tmux new-session -s panes -n first -d
$ tmux new-window -t panes -n second
$ tmux attach -t panes

現(xiàn)在,要把第一個(gè)窗口移動(dòng),作為第二個(gè)窗口的一個(gè)面板,按下 PREFIX : 鍵進(jìn)入命令模式,然后輸入這些:

join-pane -s 1

這句話的意思是“取出窗口(當(dāng)窗口中有多個(gè)面板時(shí)則指取出面板,譯者注)1 并把它添加到當(dāng)前窗口”,因?yàn)槲覀儧]有指定一個(gè)目標(biāo)窗口。

也可以使用這種方法來移動(dòng)面板。如果第一個(gè)窗口有兩個(gè)面板,可以像下面這樣指定源面板,注意我們設(shè)置窗口從 1 開始編號,而面板從 0 開始編號:

join-pane -s 1.0

在這里,我們?nèi)〕隽说谝粋€(gè)窗口的第一個(gè)面板然后把它添加到當(dāng)前窗口。

更進(jìn)一步地,甚至可以指定一個(gè)源會(huì)話,使用格式 -t [session_name]:[window].[pane] 指定一個(gè)目標(biāo)窗口。

最大化和恢復(fù)面板

有時(shí)我們只是想讓一個(gè)面板最大化顯示一會(huì),這樣就可以細(xì)看它的內(nèi)容,這時(shí)可以使用 break-pane 命令,然后再使用 join-pane 命令把它放回原處。這個(gè)操作做起來有些繁瑣,因此我們編寫一個(gè)腳本來實(shí)現(xiàn)這個(gè)功能。這是鏈接。

首先,我們釋放 UP 箭頭鍵,把它設(shè)置為最大化命令。然后,創(chuàng)建一個(gè)新的快捷鍵 PREFIX UP 來觸發(fā)這個(gè) tmux 命令串,配置如下:

unbind Up
bind Up new-window -d -n tmp \; swap-pane -s tmp.1 \; select-window -t tmp

在配置里,我們創(chuàng)建了一個(gè)名為 tmp 的新窗口。通過給它命名,可以在子序列命令里調(diào)用它。當(dāng)使用 -d 參數(shù)創(chuàng)建窗口時(shí),tmux 會(huì)在后臺(tái)創(chuàng)建這個(gè)窗口而不是把焦點(diǎn)轉(zhuǎn)到這個(gè)窗口上。然后使用 swap-pane 命令選取已經(jīng)選擇的面板和臨時(shí)窗口的已有面板進(jìn)行交換。

要恢復(fù)窗口,只需要使用 swap-pane 命令把面板從臨時(shí)窗口交換到原來的窗口里,選擇源面板,然后殺掉臨時(shí)窗口。我們把這個(gè)命令序列綁定到 PREFXI DOWN 鍵,就像這樣:

unbind Down
bind Down last-window \; swap-pane -s tmp.1 \; kill-window -t tmp

由于它使用了 last-window 命令來返回源窗口,因此這個(gè)過程看起來就像是把一個(gè)面板啪的一下最大化了,然后又啪的一下把它恢復(fù)原位置,這個(gè)簡單的例子說明了 tmux 高度靈活性。我們可以通過一個(gè)簡單的快捷鍵來自動(dòng)化實(shí)現(xiàn)一系列命令。

在面板里執(zhí)行命令

在第 3 章,我們已經(jīng)學(xué)習(xí)了如何使使用 shell 命令和 send-keys 在面板里啟動(dòng)程序,我們還可以讓 tmux 在新建一個(gè)窗口或面板時(shí)自動(dòng)執(zhí)行命令。

假設(shè)有兩臺(tái)服務(wù)器,bums 和 smithers,分別是 web 服務(wù)器和數(shù)據(jù)庫服務(wù)器。當(dāng)啟動(dòng) tmux 時(shí)我們想讓 tmux 使用一個(gè)窗口的兩個(gè)面板分別連接到這兩臺(tái)服務(wù)器上。

下面我們來創(chuàng)建一個(gè)新的名為 servers.sh 的腳本然后創(chuàng)建一個(gè)會(huì)話連接到兩臺(tái)服務(wù)器:

$ tmux new-session -s servers -d "ssh deploy@bums"
$ tmux split-window -v "ssh dba@smithers"
$ tmux attach -t servers

新建一個(gè)會(huì)話時(shí),可以把要執(zhí)行的命令作為最后一個(gè)參數(shù)傳入到 tmux 中。在這里我們先是新建了一個(gè)會(huì)話然后在第一個(gè)窗口連接到 bums 服務(wù)器,然后從會(huì)話中分離出來。之后我們使用垂直分割切分窗口然后連接到 smithers 服務(wù)器。

這個(gè)配置有個(gè)副作用:從遠(yuǎn)程服務(wù)器上退出登錄時(shí),面板或窗口會(huì)關(guān)閉。

在 OS X 系統(tǒng)的同一目錄下打開新面板

在 Linux 系統(tǒng)上創(chuàng)建 tmux 新的面板時(shí),新面板使用的是當(dāng)前面板的路徑。但是在 OS X 系統(tǒng)上,新的面板會(huì)位于啟動(dòng) tmux 會(huì)話時(shí)的那個(gè)目錄。只需要做一點(diǎn)小小的工作,就可以在打開一個(gè)面板時(shí)捕捉它的工作路徑然后自動(dòng)地切換路徑,就像 Linux 做的那樣。

為此,我們使用 send-keys 命令來調(diào)用一個(gè)腳本把當(dāng)前路徑保存到環(huán)境變量中,然后這個(gè)腳本回調(diào) send-keys 向拆分的窗口中發(fā)送命令,再把路徑更改為環(huán)境變量中保存的那個(gè)路徑。

首先,在主目錄下創(chuàng)建一個(gè)名為 ~/tmux-panes 的新文件,寫入以下內(nèi)容:

TMUX_CURRENT_DIR=`pwd`
tmux split-window $1
tmux send-keys "cd $TMUX_CURRENT_DIR;clear" C-m

然后編輯 .tmux.conf 文件來調(diào)用這個(gè)文件做垂直和水平分割。這里使用 PREFXI v 鍵和 PREFXI n 鍵,以防覆蓋了當(dāng)前已有的分割快捷鍵。代碼如下:

unbind v
unbind n
bind v send-keys " ~/tmux-panes -h" C-m
bind n send-keys " ~/tmux-panes -v" C-m

就像在之前討論過的,我們需要使用 -v 參數(shù)來水平分割窗口,使用 -h 參數(shù)來垂直分割窗口。

最后,為 tmux-panes 腳本添加執(zhí)行權(quán)限:

$ chmod +x ~/tmux-panes

在重新加載 .tmux.conf 配置文件后就可以分割面板了。

這種方法的弊端是它看起來有點(diǎn) hack。它把命令輸入到已有的 tmux 窗口并執(zhí)行腳本。也就是說它只能在一個(gè)有命令提示符的窗口里才能被觸發(fā)。所以,如果你的主窗口在運(yùn)行 Vim,這個(gè)命令是不會(huì)有效的。即便是把 send-keys 命令換成 run-shell 命令也不會(huì)有效,因?yàn)樾庐a(chǎn)生的 shell 也沒有訪問環(huán)境變的權(quán)限,因此它也就無法處理這個(gè)腳本了。但是這個(gè)腳本依然是一個(gè)比較方便的小技巧,通過自定義鍵盤快捷鍵,依然還保留了原始的命令。

6.2 管理會(huì)話

隨著使用 tmux 越來越順手,你會(huì)發(fā)現(xiàn)你會(huì)同時(shí)使用多個(gè) tmux 會(huì)話。例如,你可能會(huì)為每個(gè)程序都開啟一個(gè) tmux 會(huì)話,這樣就可以保持開發(fā)環(huán)境的相對獨(dú)立。tmux 提供了多種特性能讓你在管理這些會(huì)話時(shí)不會(huì)感到痛苦。

在會(huì)話間移動(dòng)

單機(jī)上的所有 tmux 會(huì)話都通過一個(gè)服務(wù)器進(jìn)行管理。也就是說我們能夠在一臺(tái)機(jī)器上就可以實(shí)現(xiàn)在會(huì)話之間來回移動(dòng)。

下面來演示這個(gè)過程,我們會(huì)啟動(dòng)兩個(gè)分離的 tmux 會(huì)話,一個(gè)名為 editor,它打開了 Vim,一個(gè)名為 processes 的會(huì)話則在運(yùn)行 top 命令,命令如下所示:

$ tmux new -s editor -d vim
$ tmux new -s processes -d top

可以這樣連接到 editor 會(huì)話:

$ tmux attach -t editor

然后按下 PREFIX ( 鍵進(jìn)入前一個(gè)會(huì)話,按下 PREFIX ) 則可以跳轉(zhuǎn)到下一個(gè)會(huì)話。

還可以使用 PREFIX s 鍵顯示一個(gè)會(huì)話列表,這樣就可以快速地從一個(gè)會(huì)話跳轉(zhuǎn)到另一個(gè)會(huì)話。

你可以添加自定義的快捷鍵到 .tmux.conf 文件里來綁定 switch-client 命令。默認(rèn)的配置應(yīng)該是像這樣:

bind -r ( switch-client -p
bind -r ) switch-client -n

如果你已經(jīng)配置了多個(gè)工作空間,這樣操作會(huì)極大地提高你的效率,而且它不需要分離會(huì)話再重新連接。

創(chuàng)建或連接到已有會(huì)話

到目前為止,我們學(xué)會(huì)了多種辦法在任意時(shí)刻創(chuàng)建新的 tmux 會(huì)話。然而,事實(shí)上還可以判斷一個(gè) tmux 會(huì)話是否存在,如果存在的話就連接到它。

has-session 命令返回一個(gè)可以用在 shell 腳本里的布爾值??梢杂盟?bash 腳本做一些類似這樣的事情:

if ! tmux has-session -t remote; then
    exec tmux new-session -s development -d
    # other setup commands before attaching....
fi
exec tmux attach -t development

如果修改這個(gè)腳本讓它通過參數(shù)讀取會(huì)話名稱,你就可以用它來連接或創(chuàng)建任意 tmux 會(huì)話。

在會(huì)話之間移動(dòng)窗口

可以把一個(gè)會(huì)話的窗口移動(dòng)到另一個(gè)會(huì)話里。如果已經(jīng)在一個(gè)開發(fā)環(huán)境里打開了一個(gè)進(jìn)程,現(xiàn)在想把它移動(dòng)到另一個(gè)環(huán)境中,或者想合并工作空間時(shí)會(huì)非常有用。

move-window 命令被映射到快捷鍵 PREFIX . 鍵(英文句號鍵,譯者注),這樣可以很方便地把要移動(dòng)的窗口作為當(dāng)前焦點(diǎn)窗口,按下快捷鍵,然后輸入目標(biāo)會(huì)話即可。

下面演示一下這個(gè)過程,創(chuàng)建一個(gè)會(huì)話,一個(gè)名為 editor,一個(gè)名為 processes 分別運(yùn)行了 vimtop 命令:

$ tmux new -s editor -d vim
$ tmux new -s processes -d top

我們會(huì)把 processes 會(huì)話的窗口移動(dòng)到 editor 會(huì)話里。

首先,連接到 processes 會(huì)話,就像這樣:

$ tmux attach -t processes

然后,按下 PREFIX . 鍵,然后在顯示的命令行里輸入 editor。

這會(huì)把 processes 會(huì)話里的唯一窗口移動(dòng)出來,因此 processes 會(huì)話會(huì)自動(dòng)關(guān)閉。如果連接到 editor 會(huì)話,就可以看到這兩個(gè)窗口。

也可以使用 shell 命令來完成這個(gè)功能,因此不必在合并窗口時(shí)要連接會(huì)話??梢赃@樣使用 move-window 命令:

$ tmux move-window -s processes:1 -t editor

這個(gè)命令的意思就是,把 processes 會(huì)話的第 1 個(gè)窗口移動(dòng)到 editor 會(huì)話中。

6.3 tmux 和你的操作系統(tǒng)

既然 tmux 已經(jīng)變成了你工作流的一部分,那么你肯定想讓它和操作系統(tǒng)集成地越緊密越好。在本機(jī),我們會(huì)向你展示多種方式,讓你的 tmux 和操作系統(tǒng)一起工作。

使用一個(gè)不同的 Shell

在本書中,我們使用的 shell 環(huán)境都是 bash,但是如果你更喜歡 zsh,你依然可以使用所有的 tmux 優(yōu)良特性。

可以在 .tmux.conf 文件里明確地設(shè)置默認(rèn)的 shell 環(huán)境,就像這樣:

set -g default-command /bin/zsh
set -g default-shell /bin/zsh

由于 tmux 只是一個(gè)終端復(fù)用器而并沒有擁有獨(dú)立的 shell,因此可以精確地指定使用哪個(gè) shell。

默認(rèn)啟動(dòng) tmux

可以配置操作系統(tǒng)讓它在打開一個(gè)終端時(shí)自動(dòng)啟動(dòng) tmux。通過使用會(huì)話名可以創(chuàng)建一個(gè)不存在的會(huì)話。

當(dāng) tmux 在運(yùn)行時(shí),它會(huì)把 TERM 變量設(shè)置為 screen 或者是 default-terminal 配置文件里的配置??梢栽?.bashrc 文件(OS X 系統(tǒng)是 .bash_profile 文件)里使用這個(gè)變量來確定當(dāng)前是否處于一個(gè) tmux 會(huì)話中。我們在第 2 章配置了 tmux 終端為 screen-256color,因此可以使用這樣一個(gè)腳本:

if [[ "$TERM" != "screen-256color" ]]
then
    tmux attach-session -t "$USER" || tmux new-session -s "$USER"
    exit
fi

如果沒有在 tmux 會(huì)話里,我們會(huì)嘗試連接到一個(gè)名為 $USER 的會(huì)話里,也就是當(dāng)前用戶名??梢园堰@個(gè)值替換為任意你想要的值,在這里使用用戶名能幫助我們避免沖突。

如果會(huì)話不存在,tmux 會(huì)拋出一個(gè)錯(cuò)誤,shell 腳本會(huì)把這個(gè)錯(cuò)誤解釋為 false 值。然后腳本會(huì)繼續(xù)執(zhí)行右側(cè)的命令,也就是創(chuàng)建一個(gè)以用戶名作為名稱的會(huì)話。然后退出腳本。

當(dāng) tmux 會(huì)話啟動(dòng)時(shí),它會(huì)再次運(yùn)行配置文件,但是這次它會(huì)看到我們處于一個(gè) tmux 會(huì)話中,因此就會(huì)略過這部分的后續(xù)代碼,然后繼續(xù)執(zhí)行配置文件的其他配置,確保所有環(huán)境變量都已被配置。

現(xiàn)在,創(chuàng)建一個(gè)新的終端會(huì)話時(shí),我們就自動(dòng)地連接到一個(gè) tmux 會(huì)話中。但是請小心,因?yàn)槟忝看未蜷_新的終端窗口時(shí)都會(huì)連接到相同的會(huì)話,在任意終端窗口里輸入 exit 命令都會(huì)關(guān)閉所有連接到會(huì)話的終端窗口!

把程序輸出記錄到日志里

有時(shí)需要把一個(gè)終端會(huì)話的輸出記錄到日志文件里。我們在之前已經(jīng)討論過如何使用 capture-panesave-buffer 命令來完成這些操作,但是實(shí)際上 tmux 可以通過 pipe-pane 命令把一個(gè)面板里的活動(dòng)都記錄到一個(gè)文本文件里。這很像許多 shell 里的 script 命令,使用 pipe-pane 命令可以選擇打開或關(guān)閉這個(gè)功能,而且可以在一個(gè)程序已經(jīng)運(yùn)行之后再開始使用這個(gè)命令。

要激活這個(gè)功能,在命令模式輸入命令 pipe-pane -o "mylog.txt"。

-o 參數(shù)讓我們打開了輸出功能,也就是說如果再次發(fā)送相同的命令就可以把這個(gè)功能關(guān)掉。為了更方便地執(zhí)行這個(gè)命令,我們把它添加到配置文件里并綁定一個(gè)快捷鍵。像這樣:

bind P pipe-pane -o "cat >>~/#W.log" \; display "Toggled logging to ~/#W.log"

現(xiàn)在可以按下 PREFIX P 命令來控制打開日志功能了。多虧了 display 命令(display-message 命令的簡寫),我們可以在狀態(tài)欄看見日志文件名。display 命令和狀態(tài)欄一樣能訪問相同的變量。

在狀態(tài)欄添加電池電量顯示

如果你在筆記本電腦上使用 tmux,你可能想在狀態(tài)欄里顯示電池剩余電量,尤其是終端在全屏狀態(tài)下運(yùn)行的時(shí)候。幸虧有 #(shellcommand) 變量能夠讓這個(gè)事情變得相當(dāng)容易。

現(xiàn)在我們把電池狀態(tài)添加到配置文件里。我們抓取了一個(gè)簡單的 shell 腳本,它能夠獲取剩余電池電量并把它寫入主目錄下名為 battary 的文件里。要讓 tmux 能夠使用這個(gè)腳本,要賦予它執(zhí)行權(quán)限。在終端里運(yùn)行這些命令:

$ wget --no-check-certificate \
https://raw.github.com/richoH/dotfiles/master/bin/battery
$ chmod +x ~/battery

如果在終端里運(yùn)行這個(gè)命令:

$ ~/battery Discharging

我們就會(huì)看到電池剩余電量的百分比。可以讓 tmux 通過 #(<command>) 命令把它顯示在狀態(tài)欄里。所以,要在時(shí)鐘之前顯示電池電量,需要這樣修改配置文件里 status-right 這一行:

set -g status-right "#(~/battery Discharging) | #[fg=cyan]%d %b %R"

重新加載 .tmux.conf 文件時(shí),電池的剩余電量就會(huì)顯示出來。

要想在電池充電時(shí)獲取它的狀態(tài),需要執(zhí)行這個(gè)命令:

$ ~/battery Charging

然后根據(jù)上面的方法,可以把這個(gè)命令添加到狀態(tài)欄里。這部分的工作留給你來完成。

使用這種方法更深度地定制狀態(tài)欄。只需要編寫自己的腳本然后返回你想要顯示的任意值,然后把它扔到狀態(tài)欄里。

6.4 接下來做什么?

你已經(jīng)學(xué)會(huì)了 tmux 的基礎(chǔ)你就可以做很多事情,而且你現(xiàn)在已經(jīng)對不同的配置有了一定的經(jīng)驗(yàn)。tmux 的用戶手冊,可以在終端里獲取,命令如下:

$ man tmux

這里面有完整的配置選項(xiàng)列表和所有 tmux 可用命令。

別忘了 tmux 本身也是在快速進(jìn)化之中。下一個(gè)版本將會(huì)帶來新的配置選項(xiàng),會(huì)為你帶來更高的靈活性。

現(xiàn)在你已經(jīng)把 tmux 集成到你的工作流之中了,你可以嘗試發(fā)掘一些其他的常用技術(shù)。例如,可以一起使用 tmux 和 Vim 來創(chuàng)建更高效的開發(fā)環(huán)境。你還可以在 tmux 會(huì)話里使用 irssi(一個(gè)終端界面的 IRC 客戶端)和 Alpine(一個(gè)基于終端的郵件應(yīng)用),每個(gè)程序占用你的一個(gè)面板,和你的文本編輯器并排排列,或是讓它們運(yùn)行在后臺(tái)窗口里。然后你可以從會(huì)話中分離出來,過段時(shí)間再連接到 tmux 會(huì)話中,一如既往。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號