🍨

Rust製ターミナルマルチプレクサのZellijに入門してみる

7 min read 2

K8sの基礎力を高めるため、久しぶりに Kubernetes The Hard Way (K8sをスクラッチ構築するチュートリアル)を行おうとしていたところ、あることを思い出しました。
それは、tmuxのようなターミナルマルチプレクサ(平たく言えばターミナルの画面分割や切り替えなどが簡単にできるツール)の利用が推奨されていた、ということです。
その理由としては、Hard Wayでは作業を進める上で各ノードで同じようなコマンドを何回も入力する必要があるのですが、tmuxを使えば複数ノードに対して一斉に同一コマンドを実行できるので、スムーズに作業ができるためです。
ただ、以前Hard Wayを行った時点ではtmuxにあまり習熟しておらず、かつとにかく手を動かして覚えることを目的としていた関係でtmuxを使ってはいませんでした。

一方で、今回はそろそろtmuxに入門し直そうかと思っていたところ、Zellij の存在を思い出しました。

Zellijとは

https://github.com/zellij-org/zellij

Zellij とは、tmuxやGNU screenと同種のターミナルマルチプレクサです。
こちらのツールを利用すると、tmuxと同様にターミナルを柔軟なレイアウトで分割表示することができます。
余談ですが、Zellij(ゼリージュ)の由来を調べてみたところ、タイルを組み合わせた幾何学模様のことを指すようで、分割されたターミナルのイメージと重なる良い命名だな、と感じました。

特徴としては、次の通りです。

  • インストールが簡単
    • Rust製であるため、ポータブルなシングルバイナリを配置するだけでインストールが完了
  • ユーザーフレンドリーなUI
    • 画面左下に使い方や現在のモードが常に表示されている
  • 設定ファイルのフォーマットがyaml
  • 起動時のターミナルレイアウトを指定可能
    • yamlで各画面の高さや幅を定義しておくと、最初からそのレイアウトでターミナルが起動
  • WebAssemblyプラグインに対応
    • WebAssemblyにコンパイルできる言語であれば、どんな言語でも拡張プラグインが書ける

実は数ヶ月前にZellijを発見した時点では、複数ペインで同時にコマンドを実行することができなかったため採用を見送っていたのですが、
現在では次のPRが取り込まれて利用できる状態(>=v0.6.0)となっていたため、早速使ってみることにしました。

https://github.com/zellij-org/zellij/pull/395

先に触ってみた感触として、ターミナルマルチプレクサを触ったことがない方であっても非常に導入しやすいツール であると感じたため、次節から詳しく紹介していきます。

環境

  • macOS Big Sur
  • Zellij: 0.14.0

インストール

Zellijのインストールオプションとしては、次の方法が用意されています。

  1. Cargo(Rustのパッケージマネージャー)でインストール
  2. ビルド済みのバイナリを配置

今回は後者の方法でインストールを行います。

  • Releasesページからバイナリをダウンロード
    • gzipで圧縮されているので、解凍するとzellijバイナリが出てくる

https://github.com/zellij-org/zellij/releases
  • Macであれば次の手順でバイナリを開く

https://support.apple.com/ja-jp/guide/mac-help/mh40616/mac
  • PATHが通った場所にmvして、実行権限を付与
$ mv zellij /usr/local/bin
$ chmod +x /usr/local/bin/zellij
  • バージョン確認

次のように正常にバージョンが表示されればOKです。

$ zellij -V                           
zellij 0.14.0

ハンズオン

前節まででインストールが完了しましたので、早速触っていきます。

起動

何も考えずに zellij コマンドを実行します。

$ zellij

すると、新規Sessionが立ち上がり、次のような画面が表示されます。

画面上部には現在開いているTab、画面下部にはキーバインドが並んでいます。
先ほど「Session」「Tab」という用語が登場しましたが、Zellijではtmuxと同様にSessionTabPaneという要素が存在し、それぞれ次のような意味を持っています。

  • Session: Zellijの起動単位で、最上位の要素。複数Sessionの起動も可能。1つのSessionは1つ以上のTabを持つ
  • Tab: Sessionの子要素。物理的な一枚の画面を指す。1つのTabを複数の画面に分割することができる。1つのTabは1つ以上のPaneを持つ
    • tmuxでいうところのWindowに近い
  • Pane: Tabの子要素。Tabの中で分割された画面の一枚一枚を指す

このようにSession->Tab->Paneという階層関係があり、起動直後はそれぞれ1つずつ存在します。

Paneの操作

ctrl+pを入力すると、Paneの操作モードに移行し、Paneコンポーネントで使えるコマンドが画面下部に表示されます。

ctrl+pをもう一度押すと、Paneの操作モードから抜けてターミナル操作に戻る事ができます。
これ以降Tab操作モードやSession操作モードなどが出てきますが、いずれも操作モードに入る際と同じキーバインドを入力することでハイライトが消えてそのモードから抜ける事ができます。

画面を分割したい場合は、その状態でnを入力してみましょう。

すると、画面の下半分に新しいPaneが追加されました。
この勢いで、nをさらに2回押してみましょう。

ご覧のように、トータル4つのPaneが表示されました。

操作したいPaneを切り替えるには、ctrl+pをもう一度押してPane操作モードに移行し、
矢印キーで操作したいPaneをSelectした後ENTERキーを押すことで切り替えができます。

分割したPaneを閉じる場合は、ctrl+pをもう一度押してPane操作モードに移行し、
閉じたいPaneを矢印キーで選択した上でxのCloseキーを押すと閉じることができます。

また、個々のPaneのサイズを変えたい場合は、ctrl+rでResizeモードに移行し、矢印キーを押すことで選択されたPaneの高さや幅のサイズを変更する事もできます。

最後に、説明仕切れなかった部分も含め、Paneモードのコマンド表を以下に記載します。

コマンド 意味
矢印キー 選択した方向のPaneに移動
p 次のPaneに移動
n Paneの新規作成
d 現在選択されているPaneの下部に新規Paneを作成
r 現在選択されているPaneの右部に新規Paneを作成
x 現在選択されているPaneを閉じる
f 現在選択されているPaneをフルスクリーン表示
ENTERキー Paneを選択

Tabの操作

次に、Tabの操作方法を見ていきます。
こちらは先ほどのPaneの時と同様にctrl+tを入力するとTab操作モードに移行する事ができます。
この状態でnを押すと、新規タブが作成されます。

このように、Tab #2が開きました。
元のTabに戻りたい時は、Paneの時と同様にTab操作モードに切り替えてから矢印キーを押下することで切り替えられます。

また、Tabについてはリネームを行う事ができ、Tab操作モードでrキーを押すと現在選択されているタブの名前を変えることもできます。

そして、Tab操作モードでは非常に重要なコマンドとして、s(Sync)コマンドが用意されています。
これは、同一タブの全てのPaneでテキスト入力を同期する事ができる機能です。
実際に試してみると、次のようにTab名の末尾に (Sync) が付与されて同期モードとなります。

その状態でテキストを入力してみると、このように全てのPaneで同じテキストが同期された事がわかります。
複数のサーバーにSSHして同じコマンドを投げたくなるようなシーンは往々にしてあると思いますので、ぜひ使ってみてください。

最後に、Tab操作モードのコマンド表を以下に記載します。

コマンド 意味
矢印キー 選択した方向のTabに移動
n Tabの新規作成
x 現在選択されているTabを閉じる
r 現在選択されているTabをリネーム
s 現在選択されているTabを同期モードにする
ENTERキー Tabを選択

Sessionの操作

次に、Sessionの操作方法を見ていきます。
一旦、先ほどまでのハンズオンで開いていたSessionを閉じたいと思いますので、ctrl+qでQuitします。
すると、次のようにSessionから抜けた旨が表示されます。

$ zellij                    
Bye from Zellij!

この状態でzellij list-sessionsを実行してみましょう。

$ zellij list-sessions
No active zellij sessions found.

このように、先ほどQuitしたため、アクティブなSessionは存在しないことがわかります。
それを確認した後、もう一度Sessionを起動します。

$ zellij

今度はctrl+oでSession操作モードに移行します。

すると、このようにd(Detach)コマンドが表示されますので、こちらを実行します。

$ zellij                    
Bye from Zellij!

そうすると、先ほどctrl+qでQuitした時と全く同じ表示がされますが、このままzellij list-sessionsを実行します。

$ zellij list-sessions
strong-cook

今度はSessionは閉じられておらず、「strong-cook」[1]としてアクティブなまま残っている事がわかります。
この記事を読んでくださっている方は薄々勘づいているかと思いますが、DetachがあればもちろんAttachもあるので、
表示されたセッション名に対してzellij attachしてみましょう。

$ zellij attach strong-cook

すると、元のSessionに復帰できる事がわかります。

ここまで説明したように、Sessionを閉じるときは QuitDetach という2種類の操作があり、前者は完全にSessionをクローズするのに対して、後者ではアクティブなままSessionを残す動きになる事がわかりました。
一度Sessionは閉じたいものの、後で作業を再開する予定がある場合はAttach/Detachを活用していただくと良いかと思います。

その他

Zellijを使っていく中で、Zellijのキーバインドを一時的に無効にしたくなる(e.g. ctrl+rでResizeではなくシェルのコマンド履歴検索モードに移行したい)ようなケースが出てくると思います。
そのような時はctrl+gでLOCKモードに移行する事で一時的に無効にする事ができます。

LOCKモードを解除したい場合は、他のモードと同様にctrl+gをもう一度入力することで解除ができます。

ctrl+rをはじめ、キーバインド自体の変更も可能です[2]
現在のキーバインドを確認する場合は、zellij setup --dump-configを実行すると現在のバインド設定がyamlで出力されます。

最後に

今回はZellijの基本的な使い方について見てきました。
これまで紹介してきたように、今現在どのようなモードが効いていてどのようなコマンドを入力すれば良いのかが直感的にわかりやすいつくりとなっており、インストールも非常に簡単なので、導入の敷居は低いと言えそうです。

一方で、まだBeta版ということもあって一部の動作に怪しいところがあったり(普段使いではあまり困らなそうですが)、
tmuxのペイン間のコピペのような痒いところに手が届く機能はまだなさそうなので、現時点ではtmuxから移行するというよりはまだターミナルマルチプレクサを利用していないユーザーのはじめの一歩によさそうかな、という肌感です。

なお、この他にも次のような機能があるのですが、あまりに記事の分量が大きくなってしまいそうなので、
そちらの内容については別記事(かBooksか)に切り出す予定です。

  • 起動時のターミナルレイアウト設定
  • テーマの設定
  • キーバインドの設定
  • プラグインの作成

Zellijの今後のロードマップとしては

  • Webサーバー機能: ターミナルではなくブラウザからZellij(ローカル or リモート)に接続する機能
  • セッション共有機能: 他のユーザーとリアルタイムにPaneを共有する機能
  • Smart Layout機能: Paneが追加された時などに、賢くレイアウトを再配置してくれる機能

といった面白そうな機能の開発予定があるようなので、この先さらに期待できそうです。

https://github.com/zellij-org/zellij#roadmap
脚注
  1. セッション名はランダムで振られるようです。 ↩︎

  2. 別記事にて解説予定 ↩︎

Discussion

インストール不要で動作するのは良いですね😍
追加インストール不可のターミナルマルチプレクサが入ってない環境で作業する機会がよくあるのですが
これなら使えそうです😆

コメントありがとうございます!
zellijバイナリ本体だけはどこかにインストールが必要ですが、ビルドの際に静的リンクされてるので、基本的にそれ以外のランタイムのインストールを考えなくて良いのが楽ですね😊

ログインするとコメントできます