tmux — 仮想端末でリモート仕事を安全に
GNU screen の後を継ぐ端末多重化ソフト(terminal multiplexer)。
- 1つの画面の中でウインドウを追加・分割して複数の端末を開く
- GUIアプリのタブ代わりに。
- 1つのsshセッションで複数の端末を持てる。
- ssh切断後も端末丸ごと継続され、後でまた繋ぎ直せる
- 不意のssh切断でも作業が失われない。
- 別の端末から接続しても同じ作業を継続できる。
nohupとかバックグラウンド化とか考えるより楽チン。
Homebrew で一発インストール:
brew install tmux
キーバインド
tmux 内で prefix key に続けて特定のキーを送信すると、 そのキーに応じたさまざまなコマンドを実行できる (e.g. prefix? でキーバインドを列挙)。 prefix keyはデフォルトで C-b (controlbの略記、^bと等価) だがそれはキャレット左移動に使われるべきなので後述のように変更する。
| key | command | description |
|---|---|---|
| ? | list-keys |
|
| : | command-prompt |
|
| d | detach-client |
|
| c | new-window |
|
| n | next-window |
|
| p | previous-window |
|
| l | last-window |
|
| , | rename-window |
|
| . | move-window |
|
| 0 1 2 3 | select-window -t :=N |
|
| " | split-window |
横長・縦並びに分割: 日 |
| % | split-window -h |
縦長・横並びに分割: Φ |
| ; | last-pane |
直前のペイン(往復) |
| o | select-pane -t:.+ |
番号順にペインを巡回 |
| ↑↓←→ | select-pane -U |
|
| C-↑C-↓ | resize-pane -U |
ペインサイズ変更 |
| C-o | rotate-window |
レイアウトを維持してペインを回す |
| space | next-layout |
レイアウトを変更する |
| ! | break-pane |
ペインを独立したウィンドウにする |
| [ | copy-mode |
|
| ] | paste-buffer |
コピーモード
上に戻ってスクロールしたり、その内容をコピーしたいときはコピーモードを使う。
キーボードから prefix[ で入れるほか、
set -g mouse on を設定すれば上スクロールで自然に入れる。
コピーモードでのキー操作はデフォルトだとemacs風で、
環境変数 EDITOR/VISUAL やオプション mode-keys からviに変更できる。
シェルを介さずに直接起動する場合も考えると明示的にオプション設定しておくのが無難。
| command | vi | emacs | description |
|---|---|---|---|
cancel |
q | esc | コピーモード終了 |
begin-selection |
space | C-space | 選択開始点をマーク |
copy-pipe-and-cancel |
enter | M-w | 選択範囲内を copy-command に送って終了 |
コピーと同時に終了せずモードや選択状態を維持したい場合はキーバインドを
copy-pipe や copy-pipe-no-clear に変更する。
copy-pipe* の宛先はデフォルトでtmux内のバッファになっており、
ペーストはtmux内で prefix] するしかない。
macOSで次のように設定しておけば、
⌘commandcと同じところにコピーして、
アプリを超えて⌘commandvできるようになる:
if "command -v pbcopy" "set -s copy-command pbcopy"
設定
設定ファイル: ~/.tmux.conf
https://github.com/heavywatal/dotfiles/blob/master/.tmux.conf
prefix <key>- 使えるのは
^hや^[のようなASCIIキャレット記法が存在するもの。 シェルやエディタであまり使わず左手だけで完結できるキーがいい。 tmux の頭文字で覚えやすい C-t がよかったけどfzfと衝突。 - 同じキーを
bind <key> send-prefixに設定しておけば、 2回押しのうち1回分がtmuxを貫通して伝わる。 使う頻度の低いキーとの衝突ならこれで乗り切れる。 aggressive-resize [on | off]- サイズの異なる端末からattachしたときにウィンドウサイズを変更する。
update-environment <variables>- attachするときに環境変数を親プロセスから持ち込んで既存sessionの値を上書きする。
DISPLAYやSSH_AUTH_SOCKなどがデフォルトで含まれているので、-aオプションで追加するのが無難。TERM_PROGRAMは特殊で、指定しても強制的にtmuxに上書きされる。showenv TERM_PROGRAMで上書き前の情報がとれるようにはなるので、 それを使って環境変数を再上書きすることは可能。 ただしattachの度にそこまで実行できないことには注意。 See tmux#3468.
デタッチ後しばらくしてシェルを起動すると残存セッションを忘れがちなので、
以下のようなものを .zshrc とかに書いておけば表示で気付ける。
if [ -n "$TMUX" ]; then
eval $(tmux showenv TERM_PROGRAM)
else
tmux has-session >/dev/null 2>&1 && tmux list-sessions
fi
open や pbcopy などがうまく働かなくて
reattach-to-user-namespace
が必要になる問題は既に解消された。
利用例
- リモートサーバーに ssh ログインし、
tmux の新しいセッションを開始:
ssh remote.sample.com tmux - ウィンドウを左右に分割し prefix%、
右ペインでPythonインタプリタを起動
python: - 左ペインにフォーカスを戻しprefixo、
ファイルを閲覧したり何だり
less ~/.tmux.conf - 新しいウィンドウを作って prefixc、
root仕事をしたり何だりsu - - ウィンドウを切り替える prefixl, prefixn, prefixp
- このセッションをデタッチし prefixd、
ログアウトして家に帰る
exit - 家からサーバーに再び ssh ログインして、
さっきの tmux セッションをアタッチして作業を再開:
ssh remote.sample.com tmux attach -d - セッション内のすべてのペインで
exitして終了。