【FreeBSD】仮想コンソールをマルチウィンドウ化(tmux)

確認環境

PC Thinkpad X1 Carbon 2nd Gen
OS FreeBSD 12.0-RELEASE-p6
tmux tmux 2.8

課題

下記のような場面では、GUI環境のように1画面で複数のウィンドウを見ながら作業したい。

  • マニュアルを読みながら、コマンドを試す
  • Webページを読みながら、コードを書く
  • コードを書きながら、挙動を確認する

仮想コンソールの場合、どうすればいいだろうか。

対策

tmuxというソフトを使えば、1画面上に複数のシェルを起動して同時に見ることができる。
キー操作でウィンドウのフォーカス切り替えや、サイズ調整、配置替えなどを行える。
まるでGUI環境のタイル型ウィンドウマネージャのような操作感覚。

使用イメージはこちらのサイトが分かりやすいと思う。

ここでは、下記について説明する。

  1. tmuxのインストール
  2. tmuxの構成要素
  3. tmuxの起動・中断・復帰・終了
  4. tmuxの設定例
    • 全体
    • 設定例のキーバインド
    • 補足) Paneを作成する度にシェルのログインスクリプトが走る
    • 補足) カラフルなターミナルを使う(256色モード)
    • 補足) Escキーに続けて任意キー入力時、Alt+任意キーになる
  5. 残課題) fep-uim上でtmux起動すると、日本語入力中の文字がズレる

1. tmuxのインストール

tmuxは、pkgコマンドでインストールできる。
(ルート権限で実行してね。)

> pkg install tmux  

1. tmuxの構成要素

tmuxでは、1つの画面のことを「Window」と呼ぶ。
1つのWindowは下記のような画面構成イメージ。

+------------------------+------------------------+  
|                        |                        |
|                        |                        |
|                        |                        |
|          Pane1         |          Pane2         |
|                        |                        |
|                        |                        |
|                        |                        |
+------------------------+------------------------+  
|                                                 |
|                                                 |
|                      Pane3                      |
|                                                 |
|                                                 |
+-------------------------------------------------+  
|                    Statusline                   |
+-------------------------------------------------+  

画面を構成する要素を整理すると、下記のような感じ。

  • Window
    • 1つの画面全体(GUI環境でいうところのマルチデスクトップの1つ)
    • 1つ以上の「Pane」と、1つの「Statusline」を持つ
    • Windowはユーザが任意で増やせる
  • Pane
    • MS Windowsでいうところのウィンドウ
    • 1つのPaneは1つのシェルを起動する
    • 例えば、Pane1でw3m起動、Pane2でvim起動などできる
    • Paneはユーザが縦もしくは横に画面分割して増やせる
  • Statusline
    • MS Windowsでいうところのタスクバー&システムトレイ
    • 日付や時間、アクティブなWindowの情報などを表示できる

さらにtmuxでは、Windowの集合まとめて管理する単位を「Session」と呼ぶ。
Sessionは、1つ以上のWindowから構成される。

結局、tmuxの構成要素は下記のようなツリー構造になる。

- Session 1
  - Window 1
    - Statusline
    - Pane 1
    - Pane 2
      .  
      .  
      .  
    - Pane N
  - Window 2
    - Statusline
    - Pane 1
    .  
    .  
    .  
  - Window N 
    - Statusline
    - Pane 1
- Session 2
  - Window 1
    - Statusline
    - Pane 1
  .  
  .  
  .  
- Session N
  - Window 1
    - Statusline
    - Pane 1
  - Window 2
    - Statusline
    - Pane 1

Sessionは、後述する「detach/attach」操作によって、他のSessionに切り替えられる。

2. tmuxの起動・切断・復帰・終了

起動

下記コマンドで、tmuxを起動する。

> tmux  

起動すると、tmux上に1つのPane(新たなシェル)とStatuslineが表示されると思う。
ここから、ユーザが任意のPaneやWindowを作成しながら利用していく。

もし、複数のSessionを利用するつもりなら、後でそのSessionを利用(後述のattach)する際に分かりやすいSession名前をつけておくといいかもしれない。
新しく作成するSessionの名前は、起動時に指定できる。

> tmux new -s SessionName  

中断(detach)

各Pane、Windowの状態を保持したまま、Sessionの利用を一時中断できる。
(ただし、PCの電源を落とすと消えてしまう)

このSessionの一時中断処理のことをtmuxでは「detach」と呼んでいる。

detachはキー操作で行える。
デフォルトのキーバインドなら、Ctrl+b d(Ctrl+bを押して放した後にdキー)が割り当てられている。

復帰(attach)

detachしたSessionを復帰させる操作のことを、tmuxでは「attach」と呼んでいる。
直前にdetachしたSessionにattachする場合は、tmuxの起動引数にaを渡せばいい。

> tmux a  

もし、複数のSessionをdetachしていて、任意のSessionにattachしたい場合は、-tオプションを使う。

> tmux a -t SessionName  

終了

tmux(正確にはSession)を終了するには、全てのWindowの全てのPaneのシェルを終了(exitコマンドなど)すればいい。

また、tmuxにはtmuxを制御するためのコマンドが多数用意されている。
SessionやWindowを終了するためのコマンドも用意されている。

デフォルトのキーバインドでは、Ctrl+b :でコマンド入力待ち状態になるので、その状態で下記コマンドを入力する。

> kill-session    # 現在起動しているSessionの終了  
> kill-window     # 現在フォーカスがあるWindowの終了  
> kill-pane       # 現在フォーカスがあるPaneの終了  

コマンド入力待ち状態は、Ctrl+cでキャンセルできる。

3. tmuxの設定例

tmuxの設定ファイルは、~/.tmux.confに記述する。
インストール直後は存在しないファイルなので、新しく作成しよう。

全体

下記は~/.tmux.confの設定例。

以降では、設定例のキーバインドについてと、僕がハマったポイントについて補足する。

設定例のキーバインド

tmuxで快適な生活を送るためには、キーバインド設定を自分に合ったものに変更しよう。

ここでは設定例のキーバインドでよく使いそうなものを列挙する。

設定例のPrefixキーは、デフォルトのCtrl+bからCtrl+gに変更している。
下表中ではPrefixキーは、Prefixと表記していることに注意。
例えばPrefix ?という記載は、操作的にはCtrl+g ?と読み替えて欲しい。

操作 キーバインド
キーバインド一覧表示 Prefix ?
tmuxの設定再読込 Prefix R
tmuxの画面再描画 Prefix r
スクリーンロック Prefix Ctrl+l
Paneを縦に分割 Alt+v
Paneを横に分割 Alt+s
次のPaneにフォーカス移動(時計回り) Alt+j
前のPaneにフォーカス移動(反時計回り) Alt+k
直前にフォーカスがあったPaneに移動 Prefix o
Paneのサイズ変更(左へ寄せる) Prefix h
Paneのサイズ変更(右へ寄せる) Prefix l
Paneのサイズ変更(上へ寄せる) Prefix k
Paneのサイズ変更(下へ寄せる) Prefix j
Paneの配置移動(ローテーション) Prefix Ctrl+o
Paneの配置移動(次のPaneと交換) Prefix J
Paneの配置移動(前のPaneと交換) Prefix K
現在フォーカスがあるPaneを全画面表示 Prefix z (もう1回押せば元に戻る)
Window新規作成 Prefix n
現在のWindowを削除(確認あり) Prefix c
次のWindowにフォーカス移動 Alt+K
前のWindowにフォーカス移動 Alt+J
次のSessionに切り替え Prefix L
前のSessionに切り替え Prefix H
現在のSessionをdetach Prefix d
コピーモード開始 Prefix v
コピーしたバッファ内容をペースト Prefix p
コピーしたバッファ内容を選択 Prefix Ctrl+p
キーバインド設定のフォーマット

設定例のbindから始まる行がキーバインド設定。
下記のようなフォーマットで指定する。

bind [option] BindKey Command  

BindKeyは、Prefixキーの後に入力するキーを指定する。
(CtrlキーはC-、AltキーはM-で指定する)
Commandには、実行するtmuxのコマンドを指定する。

bindの -n オプション

bind-nオプションは、Prefixキーなしの操作を可能にする。
設定例でいえば、下記のPaneのフォーカス移動。

bind -n M-j select-pane -t :.+  

Prefixキーは押さずに、Alt+jだけでフォーカス移動ができる。
ただし、-nで指定したキーは、tmux上で起動したシェルで使えなくなる点に注意。
(この例ではAlt+jvimなどのショートカットとして使えなくなる)

bindの -r オプション

bind-rオプションは、Prefixキーを一度押した後、残りのキー入力だけで連続操作を可能にする。
設定例でいえば、下記のPaneのサイズ調整。

bind -r h resize-pane -L 2  

Prefix hを押した後は、続けてhキーを連打する(もしくは押し続ける)だけで、Paneのサイズを調整できる。

補足) Paneを作成する度にシェルのログインスクリプトが走る

デフォルトだと、画面分割などでPaneを作成する度にシェルのログインスクリプトが走ってしまう。
(tcshだと、~/.loginが毎回実行される)

設定例 5行目のように、使用するシェルを指定しておけば、この挙動を防げる。

set -g default-command /bin/tcsh  

補足) カラフルなターミナルを使う(256色モード)

画面をカラフルに活用したい場合、tmuxでは256色モードがサポートされている。
設定例 22行目の下記を指定すればいい。

set -g default-terminal screen-256color  

X-Window上で使用する場合、設定例 23行目の下記設定も必要かもしれない。
ただ、僕の環境で下記設定を行うと、仮想ターミナル環境で動かなくなったので、設定例では行頭に#を入れてコメントアウトしている。

set -g terminal-overrides "xterm:colors=256"  

もし、256色モードが有効になってなさそうなときは、tmux起動時に-2オプションを付けると、256色モードを強制できるので試してみるといいと思う。

> tmux -2  

補足) Escキーに続けて任意キー入力時、Alt+任意キーになる

デフォルトだと、Escキーを押した後に続けて何か任意のキーを入力した際、任意のキーがAltキーとの同時押し扱いになってしまう。

例えば、Esc aAlt+aEsc cAlt+cといった感じ。
vimのように頻繁にEscキーを使うソフトではとても厄介な挙動。

これを防ぐには、設定例 61行目の下記設定を行えばいい。

set -s escape-time 0  

4. 残課題) fep-uim上でtmux起動すると、日本語入力中の文字がズレる

uim-fep上で、tmuxを起動した場合、日本語入力に課題がある。

それは、日本語入力中(変換前)にカーソル位置が入力開始位置に戻ってしまうのだ。
その結果、入力中の文字が後から入力した文字によって上書きされてしまい、もはや何を入力しているか分からない表示になる。
入力確定後に、画面の再描画処理が走れば正常な表示になるが、結構なストレスになる。

僕の場合は、tmux起動後に日本語入力が必要なPaneでuim-fepを起動することでこの事象を回避している。
ただ、uim-fepの起動はちょっと遅いので、やはり最初だけuim-fepを起動した上でtmuxを起動したいのだけれども、今のところ対策が見つかっていない。

何か原因や対策に心当たりのある方は、コメントでご教授頂けると助かります。

ちなみにこの事象は、tmuxと似たようなソフトのscreenでは発生してなさげ。
どうしても気に入らない人は、screenを試してみる価値はあると思う。

最後に

tmuxには、プラグインという形で拡張機能が提供されている。
例えば、StatuslineにCPUの使用率やバッテリーの状態を表示したりできる。

興味のある方は調べてみると幸せになれるかも。

参考

以上。