Heavy Watal

tmux — 仮想端末でリモート仕事を安全に

https://tmux.github.io/

GNU screen の後を継ぐ端末多重化ソフト(terminal multiplexer)。

1つの画面の中でウインドウを追加・分割して複数の端末を開く
GUIアプリのタブ代わりに。
1つのsshセッションで複数の端末を持てる。
ssh切断後も端末丸ごと継続され、後でまた繋ぎ直せる
不意のssh切断でも作業が失われない
別の端末から接続しても同じ作業を継続できる
nohup とかバックグラウンド化とか考えるより楽チン cf. nohup

Homebrew あるいはLinuxbrewで一発インストール: brew install tmux

キーバインド

tmux 内で prefix key に続けて特定のキーを送信すると、 そのキーに応じたさまざまなコマンドを実行できる。 prefix keyはデフォルトで C-b (control-bの略記)だが 後述の設定で C-t に変更することにする。 (e.g. C-t ? でキーバインドを列挙)。

key command description
? list-keys
: command-prompt
d detach-client
[ copy-mode
] paste-buffer
c new-window
n next-window
p previous-window
l last-window
, rename-window
split-window 横長・縦並びに分割
% split-window -h 縦長・横並びに分割
; last-pane 直前のペイン(往復)
select-pane -U
select-pane -D
select-pane -L
select-pane -R
o select-pane -t:.+ 番号順にペインを巡回
C-o rotate-window レイアウトを維持してペインを回す
space next-layout レイアウトを変更する
! break-pane ペインを独立したウィンドウにする
x confirm-before kill-pane
& confirm-before kill-window

コピーモード

上に戻ってスクロールしたり、その内容をコピーしたいときはコピーモードを使う。 コピーモード中のキー操作はデフォルトでは emacs 風になっている。

  1. C-t [ でコピーモードに入る
  2. C-space でコピー開始点をマーク
  3. C-w で終点をマークし、コピーモードを出る
  4. C-t ] でペースト

設定ファイルに bind-key -t emacs-copy C-w copy-pipe "pbcopy" と書いておけばコピー内容がMacのクリップボードにも送られるので、 普通にcmd-vでペーストできる。

設定

設定ファイル: ~/.tmux.conf

https://github.com/heavywatal/dotfiles/blob/master/.tmux.conf

prefix 変更
C-b はキャレット左移動に使われるべきなので、 zshemacs で使わない C-t に変更する。 tmux の頭文字で覚えやすいし、b より若干近い。
起動時ウィンドウサイズ変更 aggressive-resize
サイズの異なる端末からアクセスしたときに随時ウィンドウサイズ変更
Mac open 問題

tmux 内だと open がうまく働かないのでそれを回避するために reattach-to-user-namespace をインストールして挟む:

% brew install reattach-to-user-namespace

利用例

  1. リモートサーバーに ssh ログインし、 tmux の新しいセッションを開始:

    % ssh remote.sample.com
    % tmux -2u
    
  2. ウィンドウを縦に分割し、右ペインでPythonインタプリタを起動:

    [C-t %]
    % python
    
  3. 左ペインにフォーカスを戻し、ファイルを閲覧したり何だり:

    [C-t o]
    % less ~/.tmux.conf
    
  4. 新しいウィンドウを作って root 仕事をしたり何だり:

    [C-t c]
    % su -
    Password:
    
  5. ウィンドウを切り替える:

    C-t l
    C-t n
    C-t p
    
  6. このセッションをデタッチし、ログアウトして家に帰る:

    [C-t d]
    % logout
    
  7. 家からサーバーに再び ssh ログインして、 さっきの tmux セッションをアタッチして作業を再開:

    % ssh remote.sample.com
    % tmux attach -d
    

備忘

デタッチ後しばらくしてシェルを起動すると 既に存在しているセッションを忘れがちなので、 以下のようなものを .zshrc とかに書いておく。

tmux has-session >/dev/null 2>&1 && if [ -z "${TMUX}" ]; then
    echo '% tmux list-sessions'
    tmux list-sessions
    echo '% tmux list-windows -a'
    tmux list-windows -a
fi

ssh 先で即 tmux

以下の様なzsh関数を sshmux とかいう名前で定義する

if [ -n "$1" ]; then
    ssh -t $* "tmux -2u attach -d || tmux -2u"
else
    echo "$0: missing hostname"
    return 1
fi

さらに .zshrccompdef sshmux=ssh と書いておけば補完もいい感じになる。

関連書籍