# 第 5 章 使用 tmux 結對編程
到目前為止,我們已經學習了日常使用 tmux 以及修改配置。而 tmux 最受開發人員歡迎的功能之一就是結對編程。那是我第一次使用 tmux,當我的朋友向我介紹 tmux 的眾多功能時我立刻就喜歡上了這個功能。
結對編程有很多好處。和其他開發人員一起工作能夠幫你發現許多你無法自己看到的事情,除非你們身處同一位置,否則結對編程就會變得相當困難。使用例如 iChat,Skype 甚至是 GoToMeeting 這種屏幕共享的軟件會占用相當多的帶寬,而且在網絡狀況不好時就會變得非常糟糕。在本章,我們會學習使用 tmux 進行結對編程,之后你就可以和另一位開發人員一起遠程工作了,甚至可以使用糟糕的賓館 WiFi 網絡。
和遠程用戶協作有兩種方式。第一種方式需要創建一個新的用戶賬戶,你和他人一起共享這個賬戶。在這個賬戶下配置 tmux 和開發環境,然后把它作為一個共享的工作空間。第二種辦法是使用 tmux 的 sockets 連接,這樣你就可以讓第二個用戶連接到你的 tmux 會話中而無需共享你的賬戶信息。
這兩種方法都有一種固有的安全缺陷:它們能讓他人看到你的屏幕信息和你的賬戶。你可能在放任某人任意查看你的文件。要解決這個問題,最好使用一個中間服務器來進行結對編程。使用一個便宜的 VPS 或是一個用 VirtualBox([鏈接](https://www.virtualbox.org/))或 Vagrant([鏈接](http://vagrantup.com/docs/getting-started/index.html))創建的虛擬機,你可以快速地創建一個用于結對編程的開發環境。在本章,我們會學習在遠程服務器上分別使用這兩種進行結對編程。
## 5.1 使用共享賬戶結對編程
使用共享賬戶是和他人共同協作的最簡便的方式。在一個 nutshell 里,你可以開啟機器上的 SSH 訪問權限,將它作為主機,然后在機器上安裝并配置 tmux,之后再創建一個 tmux 會話。第二個用戶可以使用相同的賬戶登錄到這臺機器里然后連接到剛才創建的 tmux 會話中。通過使用 SSH 公開密鑰,可以讓登錄過程變得透明化。下面我們來討論這個過程。假設我們在使用一臺名為 puzzles 的服務器,它使用 Ubuntu 操作系統并且已經安裝了 SSH 后臺程序。
首先,在服務器上創建一個名為 tmux 的用戶賬戶。這個賬戶專門用于結對操作。
```
tmux@puzzles$ adduser tmux
```
使用新創建的賬戶前,需要配置這個賬戶讓它添加其他開發人員的 SSH 密鑰,這樣他們就可以通過這些密鑰來登錄這個賬戶。可以在 tmux 賬戶下創建 `~/.ssh/authorized_keys` 文件來完成這個操作。首先使用 `su` 命令切換到 tmux 賬戶:
```
tmux@puzzles$ su tmux
```
然后要創建 `.ssh` 目錄和 `.ssh/authorized_keys` 文件,并為它們配置相應的文件權限。確保只有 tmux 這個用戶可以讀、寫或執行這些文件。命令如下:
```
tmux@puzzles$ mkdir ~/.ssh
tmux@puzzles$ touch ~/.ssh/authorized_keys
tmux@puzzles$ chmod 700 ~/.ssh
tmux@puzzles$ chmod 600 ~/.ssh/authorized_keys
```
接下來,就可以把公鑰傳輸到這臺服務器上了。在桌面工作機上,生成本機的公鑰然后上傳到服務器:
```
$ scp -p id_rsa.pub tmux@puzzles.local
```
然后在服務器上,把公鑰添加到 `authorized_keys` 里。
```
tmux@puzzles$ cat id_rsa.pub >> ~/.ssh/authorized_keys
```
其他需要這個共享賬戶登錄到服務器上的所有人都要重復上述過程。
從這里開始,我們來配置 tmux,文本編輯器,編譯器,編程需要和版本控制系統,就像在其他開發環境要做的那樣。然后在服務器上創建一個新的 tmux 會話。
```
tmux@puzzles$ tmux new-session -s Pairing
```
團隊中的其他成員可以登錄到服務器上然后通過以下命令連接到這個會話中:
```
tmux@puzzles$ tmux attach -t Pairing
```
然后就可以在同一個項目里共同協作了。當然,我們可以從會話中分離出來在后來再重新連接到這個會話,也就是說可以讓開發環境一次就運行數天甚至數周。這樣只要有一個支持 SSH 的終端就可以在任何時間、任何地點都能連接到這個開發環境了。
## 5.2 使用共享賬號和組會話
當兩個人連接到同一個 tmux 會話時,他們通常會看到相同的內容并在同一個窗口里交互。但是很多時候人們希望能夠在獨立的、不同的窗口工作而不用被完全控制。
使用“組會話(grouped session)”可以實現這個功能。下面我們來演示一下,首先先在遠程服務器上創建一個新的會話叫做 groupedsession。
```
tmux@puzzles$ tmux new-session -s groupedsession
```
然后,另一個用戶不去連接到這個會話,而是通過“創建一個新的會話”來加入到這個會話里,他需要指定原始會話 groupedsession,然后再指定一個他或她自己的會話名,就像這樣:
```
tmux@puzzles$ tmux new-session -t groupedsession -s mysession
```
當第二個會話啟動時,兩個用戶都可以同時在這個會話里進行交互,就像是第二個用戶已經連接到這個會話一樣。但是,每個用戶可以創建相互獨立的窗口。因此,如果新用戶創建了一個窗口,都會在狀態欄里看到新的窗口出現了,但是用戶仍然會處于當前工作的窗口!這對那些“嘿,我有個想法我先去試試”的時刻特別適合,或者有時候有人想用 Emacs 而有人想用 Vim 的時候也很合適,就像圖13(兩個用戶共享同一個會話)所示的那樣。

圖13 - 兩個用戶共享同一個會話
第二個用戶可以使用 `kill-session` 命令殺死他或她的會話,而原始會話依然會存在。但是,如果所有的窗口都關閉的話那么這兩個會話都會被殺死。
使用共享賬戶和 tmux 是結對編程最簡單的方式,但是有時候我們并不是總是愿意和團隊成員共享賬號。下面我們來看看另一種方式。
## 5.3 使用獨立賬戶和 Socket 結對編程
使用 tmux 提供的 socket 支持,可以創建讓多個用戶非常容易連接的 tmux 會話。
首先,我們創建兩個新的用戶賬號:一個名為 ted,另一個名為 barney。
```
tmux@puzzles$ sudo adduser ted
tmux@puzzles$ sudo adduser barney
```
接下來,創建“tmux”分組以及 `/var/tmux` 文件夾用來保存共享會話。
```
tmux@puzzles$ sudo addgroup tmux
tmux@puzzles$ sudo mkdir /var/tmux
```
要更改 `/var/tmux` 目錄的組權限,這樣 tmux 組就能訪問它了:
```
tmux@puzzles$ sudo chgrp tmux /var/tmux
```
然后修改文件夾的權限讓新的文件都能被所有的 tmux 組內用戶訪問:
```
tmux@puzzles$ sudo chmod g+ws /var/tmux
```
最后,添加 Ted 和 Barney 用戶到 tmux 組內。
```
tmux@puzzles$ sudo usermod -aG tmux ted
tmux@puzzles$ sudo usermod -aG tmux barney
```
### 創建并共享會話
之前,我們已經使用過 `new-session` 命令來創建會話,但是那會使用默認的 socket 位置,我們是無法對它進行操作的。因此我們在這里不會創建命名會話,而是通過 `-S` 參數來創建我們自己的會話。
我們先登錄 ted 賬戶然后使用 socket 創建一個新的 tmux 會話:
```
ted@puzzles$ tmux -S /var/tmux/pairing
```
在另一個終端窗口里,可以登錄 barney 然后連接到這個會話。連接時不必指定會話名,我們需要做的就是指定 socket 連接和 socket 文件的位置,就像這樣:
```
barney@puzzles$ tmux -S /var/tmux/pairing attach
```
barney 用戶現在已經連接到 tmux 會話而且他看到的就是 ted 用戶所看到的內容。
需要注意的一點是,使用這種方法來使用 tmux 時,`.tmux.conf` 文件使用的配置是第一個啟動這個會話的用戶的配置。使用兩個獨立的賬戶并不意味著每個賬戶都可以在 tmux 會話里使用各自的配置文件,而是說他們可以根據其他的目的來定制他們的賬戶,然后在需要時都可以初始化他們所獨有的 tmux 會話。
## 5.4 接下來做什么?
現在你已經學會了如何通過 tmux 與他人分享屏幕,你可以使用它來進行遠程訓練、在開源項目上進行即興合作,或者是遠程演示。
另外,還可以使用這個技術在你的生產服務器上開啟 tmux 會話,加載監測工具或者控制臺,然后從會話分離出來,讓這些工具一直在后臺運行。然后可以在你的機器上連接到這個會話,所有的一切都如你斷開連接時那樣。我曾經在我的開發環境上就做過類似的事情。我在一個 VPS 上配置了 tmux,然后在家里使用一臺 iPad,一個 SSH 客戶端以及一個藍牙鍵盤就可以寫代碼了。即便是在 3G 網絡下這樣做依然很流暢。
結對編程和遠程協作只是 tmux 應用在工作時提高工作效率的兩個例子。在下一個章節,我們會學習在使用 tmux 窗口、面板和系統時其他更加高級的功能。
### 以備參考
|命令 | 描述|
|---|---|
|` tmux -S [socket]`| 使用 socket 創建一個新的會話 |
|` tmux -S [socket] attach`| 連接到一個已有的 socket 會話 |
|` tmux new-session -t [existing session] -s [new session]`| 創建一個到組會話的連接 |