VISASQ Dev Blog

ビザスク開発ブログ

tmuxの知られざるパワフルな機能を紹介してみる

アイキャッチ はじめまして。エキスパート/lite 開発 の倉光と申します。

今回初の記事投稿として、私が日々愛用している tmux の紹介ができればと思います。

自己紹介

本編に入る前に、簡単に自己紹介をさせてください。

私は 2022 年 8 月にビザスクに入社し、気がついたら約 1 年ほど経っていました。

ビザスクに入社する以前は、インフラ系のメーカーで開発職として製品開発に従事していました。また、大学の出身学部も物理系であったため、 ビザスクに入社するまではプログラミングとは無縁のいわゆるエンジニア未経験として異業種異分野からジョインして、今は既存サービスの改善であったり、プロジェクトの開発に日々従事しています。

そして、テックブログって一体どんな内容を書けばいいんだ・・ネタが思い浮かばん・・と先延ばしにしていたら日々の開発に圧倒されているうちに丸 1 年経過していたことに驚き、遅ればせながら今記事を執筆しています。

tmux とは

tmux は terminal multiplexer であり、1 つのスクリーンから複数端末を作成・制御することができるツールです。

他にも端末とは別でセッション管理をしてくれるため、ターミナルソフトを一度閉じても復旧できる利点があったりします。

私の tmux との馴れ初めは、入社するまでは tmux はおろか、これまでずっと Windows ユーザだったこともあり、はじめて Mac を使い始めたときは

  • zsh・・? bash しか知らんが。
  • iTerm2・・? ターミナルソフト・・?? ほぼ VSCode のターミナルからしかコマンド実行したことないんだが。

の知識レベルでした。

そこからターミナル周りを色々いじっていくうちに、ふと iTerm2 は Mac だけなのでクロスプラットフォームで動作できるターミナルソフトにしたいな〜と思い立ち、 描画が早そうな Alacritty を使ってみるか〜と考え、 Alacritty はタブ的な機能が搭載されていないため、タブないのはさすがにつらいので tmux 頑張って覚えるか〜という流れから入り、最初覚えるまで悪戦苦闘しながら、今では愛用ツールになりました。

そんな tmux はセッション管理してくれるだけでも十分強力なツールではあるのですが、今回はそれ以外のあまりスポットを浴びてなさそうな更にパワフルな機能(外部プラグインも含めて)を何点かピックアップすることで、 tmux に興味が出てくれる人が増えてくれれば幸いです。

(なお、今回は tmux の基本的な概要や設定・操作方法は省略させていただきます。)

tmux のここがすごい

複数画面(ペイン)の同時操作

ターミナルの 1 タブ(tmux ではウィンドウと呼ぶ)内で画面分割をして操作することがあると思いますが、複数の分割画面(tmux ではペインと呼ぶ)に共通の操作をしたいときがある場合と思います。

その際、tmux ではsynchronize-panesといって 1 ウィンドウ上のすべてのペインに対して、同時にコマンドを入力することができます。

.tmux.confで以下のようなキーバインドを設定すると、prefix → e のコマンドでsynchronize-panesの ON/OFF を切り替えることができます。

bind e if-shell -F "#{==:#{pane_synchronized},0}" "set synchronize-panes on" "set synchronize-panes off"

また、さらなる応用としてtmux-xpanesという外部ツールを用いると、ブレース展開等で引数を展開して渡すことで、画面分割をしつつ各画面で引数ごとのコマンドを実行するということもできるそうです。

分割画面のズーム

上記のように画面を分割すると、複数画面の状況を一度に見ることが出来るので便利な一方、1 画面が小さくなってしまい 1 画面の内容をじっくり見たいというときに見ずらい場面があると思います。

その際、tmux では一時的に単一の画面を最大化することができます。

デフォルトで prefix → zキーバインドに設定されているため、ショートカットキーでズーム拡大/縮小させることができます。

tmux resize-pane -Z

tmux では、通常のウィンドウ作成の他にも既存画面上に popup window を表示させることができます。

.tmux.confで以下のようなキーバインドを設定すると、prefix → ctrl + p のコマンドでpopup windowの表示 ON/OFF を切り替えることができます。

bind C-p popup -xC -yC -w95% -h95% -E -d "#{pane_current_path}" '\
  if [ popup = $(tmux display -p -F "#{session_name}") ]; then \
    tmux detach-client ; \
  else \
    tmux attach -c $(tmux display -p -F "#{pane_current_path}") -t popup || tmux new -s popup ; \
  fi \
'

また popup window を表示するだけでなく、 表示後に実行するコマンドも設定できるため、今いる画面をいじらずに popup window 上に決まったコマンド内容を表示できます。

例えば私はgit add周りの操作では gitui という TUI を用いており、以下の設定で prefix → ctrl + dで gitui を popup window 上に表示させることができます。

bind C-d popup -xC -yC -w95% -h95% -E -d "#{pane_current_path}" "gitui"

buffers を活用したペイン間でのやり取り

tmux ではターミナル上でのコピーした内容をバッファで管理しており、これらを適宜各画面から参照することができます。

つまり、あるペイン上でコピー&バッファに格納した内容を別ペインから参照することができます。 これらバッファと popup window を活用することで、popup window で選択・出力した内容をバッファ経由で今いるペイン上に出力することができます。

例として、自分は忘れっぽいために普段 navi を使用して自分用のコマンドのチートシートを作っています。 .tmux.confで以下のような設定すると、prefix → ctrl + g のコマンドで navi widget を popup window で開いて、選択・出力した内容を今いるペイン上に出力することができます。

bind C-g popup -xC -y "#{popup_pane_bottom}" -w95% -h40% -E '\
  window=$(tmux display -p -F "#S:#I.#P") && \
  export FZF_DEFAULT_OPTS="-m --layout=reverse --border" && \
  navi --print | tr -d "\n" | tmux load-buffer -b tmp - && \
  tmux paste-buffer -drp -t $window -b tmp \
'

これのいいところは、今いるペインが普段使用しているカスタマイズされたシェルに限らず、 python 等の REPL・MySQL 等のコマンドラインツール・docker コンテナ内のログインシェル・Vim などであってもバッファを介して今いるペインに出力出来る点です。

pipe-pane によるペイン間のやりとり

上記は buffers を通してペイン間でやりとりしましたがそれ以外にも、あるペイン内容を別のペインに出力(パイプ)することができます。

別のペインにはターミナルのデバイスファイルに書き出すことで出力することができます。

たとえば、以下のようにあるペイン内容の一部を grep で filter した内容をリダイレクトすることで、あるペインの一部内容を別ペインに出力することができます。

# tmux pipe-pane -t {出力元のターゲットペイン} 'cat | grep "{grepしたい文字列}" >> {出力先のペインのデバイスファイル}'
# パイプを止めるには、tmux pipe-pane -t {出力元のターゲットペイン}を再度実行します
# そのため所定のタイミングでパイプを止められるように、read ; tmux pipe-pane -t {出力元のターゲットペイン}も合わせて実行しています
# 例.
tmux pipe-pane -t 6:1.0 'cat | grep "8" >> /dev/ttys001' ; read ; tmux pipe-pane -t 6:1.0

これ以外にももちろん、ペイン表示内容をファイルに保存することができたり、標準出力・エラー標準出力に分けて出力などもすることができます。

tmux 再起動後の復旧

ここからは tmux plugin の内容です。

(tmux は plugin を導入することで、定番設定をプラグイン側が設定してくれたり、追加機能を加えたりすることができます。tmux plugin も色々とあるのですが、今回は推奨レベルのものを紹介できればと思います。)

tmux はセッション管理してくれますが、tmux 自体を kill-server (PC 再起動など)してしまうと当然、起動プログラム・作業ディレクトリ・ペインレイアウトなどの情報が失われてしまいます。

しかし、tmux-resurrectを利用して tmux 環境を保存することで、 tmux kill-server をした後でも前回保存済みの作業ディレクトリ・ペインレイアウト情報を復旧することができます。

さらにすごい点が、

  • Restoring pane contentsの設定をすると、kill-server 前に画面に表示されていた内容も合わせて復旧してくれます。
  • Restoring programsの設定をすると、tmux 起動時に合わせて、restore してほしい一部プログラム(開発サーバなど)も自動で復旧してくれます。

また、tmux-resurrect は手動で適宜 tmux 環境を保存しなければならず、いきなり PC が落ちてしまうなどしてしまうと最新の状態では復旧できないのですが、tmux-continuumを用いることで、tmux 環境をデフォルトでは 15 分間ごとに定期的に保存してくれるため、保存忘れも防ぐことができます。

# Tmux Plugin Manager
set -g @plugin 'tmux-plugins/tpm'

set -g @plugin 'tmux-plugins/tmux-resurrect'
# ペイン内容の保存をONに
set -g @resurrect-capture-pane-contents 'on'
# 例えば、makeコマンドでの開発サーバやpythonのREPLを起動することが多いので以下設定をしています
set -g @resurrect-processes '"~make" "~python"'

set -g @plugin 'tmux-plugins/tmux-continuum'
# tmux起動時の自動リストアをONに
set -g @continuum-restore 'on'

まとめ

あまりピックアップされているのを見かけない tmux のパワフルな機能をいくつか紹介させていただきました。

いろいろ楽しいことできそうと思ったそこのあなた、tmux を少しでも使ってみようかなと興味をもらえたら嬉しいです。

そして、tmux をすでに使っているそこのあなた、tmux は他にも色々出来ることがありまだまだ把握できていないことも多いので、ぜひとも他にも知られざる機能・ノウハウ等を教えてください!

tmux は 2023/8/30 現在の最新 Ver は 2022/6/9 リリースの 3.3aで、例年のペースでいくとそろそろ 3.4 が出てくるのでしょうか・・?

次のバージョンが出てくるのを待ちつつ、本記事は締めたいと思います。

(2024/02/14追記)

2024/02/13にver3.4がリリースされましたね!

sixel対応が入ったりしています(自分も隙を見て触ってみたいと思います)