ターミナルマルチプレクサとして GNU Screen を普段使っていますが、 tmux の方が活発に開発されてる様に見えたり 乗り移ってく人も沢山居るみたいなので気になって何度か試してみましたが、 イマイチ違いを吸収出来ずにScreenに戻ってきてました。
無理に移行する理由もそれ程無いですが、また試してみたので 取り敢えず違いなどのメモ。
- 設定ファイル
- Prefix (Escape)
- コマンドモード
- キー設定一覧
- デタッチ/アタッチ
- キーバインド
- コピーモード/履歴スクロールバック
- Session/Layout/Window/Pane
- split
- 全Paneに同時入力
- swap-paneの問題
- Status表示
- .bashrcなどでの判断方法
- 違いが理解できたら
設定ファイル
screen | tmux | |
---|---|---|
ファイル名 | ~/.screenrc | ~/.tmux.conf |
共にコメントは#
から右がコメントになります。
現在の設定ファイル:
Prefix (Escape)
screen | tmux | |
---|---|---|
デフォルトキー | Ctrl-a | Ctrl-b |
共にデフォルトはコマンドラインで良く使うキーなので変更必須。
(screenの方は単にアルファベットの最初のキーだからa
なのか、左端で押しやすいからなのか?
まだ分かる気がしますが、tmuxの方は単にscreenとは違うもの、と言う意味でb
なのか?
いずれにしろ何方も何故それにしたか微妙。)
変更方法(Ctrl-qへ):
screen:
# Escape
escape ^Qq
tmux:
# Prefix
set-option -g prefix C-q
unbind-key C-b
bind-key C-q send-prefix
以下、Prefixの入力はPrefixと書いて行きます。
コマンドモード
共にPrefix :でコマンドモードに入れる。 以下、(:<command>)と書いてある物はコマンドモードでの入力の意味です。
キー設定一覧
screen | tmux | |
---|---|---|
Help | Prefix ?/(:help) | Prefix ?/(:list-keys) |
共にPrefix ?で一覧が見れます。
デタッチ/アタッチ
screen | tmux | |
---|---|---|
セッション一覧表示 | $ screen -ls | $ tmux ls |
アタッチ | $ screen -r [<session number>] | $ tmux attach-session [-t <session number>] |
デタッチ | Prefix d/(:detach) | Prefix d/(:detach-client) |
tmuxの方は引数をサブコマンドみたいに使います。
サブコマンド系はそれぞれ短縮されたaliasが用意されてますが
(attach/detach等)、aliasでなくても短縮してそれが他と被って無ければ使えます。
例えばattach-sessionの場合は、a
で始まるコマンドが他にないので
tmux a
だけでもtmux attach-session
と同意になります。
detach-client
だと、他にdelete-client
などがあるので
det
まで入れると認識してくれます。
なので、attach
やdetach
ではaliasそのものは実は意味ない感じですが、
上でも使ってるls
なんかはlist-session
のaliasです。
また、screenの場合は-r
では既に接続されているセッションには接続出来ません。
-x
を使うと既に接続してるセッションへもマルチ接続が可能です。
選べる複数のセッションがある場合にはセッション番号を指定してあげないといけません。
一方、tmuxの方はそれらの区別は無く、接続されてるものでもattach-sessionで接続出来ます。 この際、セッション番号を指定しないと、
- まず接続されてないセッションの中から最後にデタッチされたセッション
- 全て接続中なら最後にアタッチされたセッション
の順で探して接続します。
キーバインド
screen | tmux | |
---|---|---|
基本バインド | bind <key> <comamnd> | bind-key <key> <command> |
Ctrlの記述 | ^a等^ を使う |
C-a等C- を使う(^ でも可) |
コピーモードの設定 | bindkey -m <key> <comamnd> | bind-key -t vi-copy <key> <command> |
シェルコマンド | bind <key> ‘exec /bin/sh -c “<shell command>” | bind-key <key> run-shell “<shell command>” |
複数コマンド | bind <key> eval ‘<command1>’ ‘<command2>‘… | bind-key <key> ‘<command1>’ \; ‘<command2>’ \;… |
submode的な | bind <key> ‘command -c sub’、の後bind -c sub <key> <command> | bind-key -r <key> <command> |
追記: 2015/01/06
tmuxのヘルプを読み直したらCtrlはscreenの様に^a
でも出来る
事に気づいたので追記。
追記ここまで
tmuxの方はbind
がbind-key
のalias設定されてるので
bind
でもOK。
また、run-shell
もrun
がalias設定されています。
コピーモードの設定はtmuxではvi/emacsモードがあり、上のはviモードの設定。
emacsモードの方を変更したい場合は-t emacs-copy
で。
複数のコマンドを指定したいときは、screenではeval
を使った後、
コマンド毎にクォートして羅列していきます。
一方、tmuxの方はコマンドの間に;
をエスケープした\;
を入れてつなげていきます。
また、tmuxではconfirm-before
というコマンドが使えて
bind-key x confirm-before -p "kill-pane #P? (y/n)" kill-pane
の様に通常コマンドの前に書くと、 実行時に実際に実行する前に確認してくれます。 これもscreenに無いtmuxの賢い機能。
submode的な、と書いたのはキー入力単体でコマンドを送れる様なモードのことです。
screenとtmuxでは基本的には違うものですが、
screenではcommand class
を設定することでキー入力後にさらに特殊なキー入力待ちを
することが出来、これを再帰的に行うことでsubmode的な動きが出来ます。
一方、tmuxでは-r
を指定することで一度他のコマンドを送った後に2回目以降
Prefix無しでキーを送れるようになります。
例えば複数に分けた領域の1つを連続的に広げたり狭めたりしたいとき、 screenでは
# Resize window
bind e eval 'command -c resize' 'echo "Resize window"'
bind ^e eval 'command -c resize' 'echo "Resize window"'
bind -c resize h eval 'command -c resize' 'resize -h -1'
bind -c resize l eval 'command -c resize' 'resize -h +1'
bind -c resize j eval 'command -c resize' 'resize -v +1'
bind -c resize k eval 'command -c resize' 'resize -v -1'
bind -c resize ^h eval 'command -c resize' 'resize -h -1'
bind -c resize ^l eval 'command -c resize' 'resize -h +1'
bind -c resize ^j eval 'command -c resize' 'resize -v +1'
bind -c resize ^k eval 'command -c resize' 'resize -v -1'
みたいにするとPrefix eを押した後、 hやlで左右に連続的に広げたり狭めたり出来ます。
一方、tmuxで同じような事をしたい場合は
# Resize pane
bind-key -r C-y resize-pane -L
bind-key -r C-u resize-pane -D
bind-key -r C-i resize-pane -U
bind-key -r C-o resize-pane -R
の様にするとPrefix Ctrl-yとした後、 Ctl-yやCtl-oで連続的に 幅を広げたり狭めたり出来ます。
tmuxの方が簡単に設定できますが、
screenのcommand class
は理解できると色々複雑な事が出来るので
一長一短な感じ。
コピーモード/履歴スクロールバック
screenではコピーモードは基本、viのキーバインドですが 1、 tmuxの方はemacsモードとviモードが選択出来ます。
デフォルトはemacsですがVISUAL
またはEDITOR
という環境変数が
vi
を含む値(i.e. vim
)だとviモードになります。
または
set-window-option -g mode-keys vi
と設定しておくとviモードになります。
(emacsモードにしたいならvi
の代わりにemacs
)
以下はviモードの話。
screen | tmux | |
---|---|---|
コピーモード開始 | Prefix [ | Prefix [ |
選択開始 | Space | Space |
選択完了 | Space | Enter |
行選択 | Spaceの代わりにyで選択開始 | Spaceの代わりにV(:select-line)で選択開始 |
矩形選択 | cで左端指定、Cで右端指定 | 選択開始後、v(:rectangle-toggle)で矩形選択へ |
履歴保存行 | defscrollback <n lines> (default 100) | set-option -g history-limit <n lines> (default 2000) |
search | /、?、n、N like vim | /、?、n、N like vim |
検索時にwarpする | defaultでoff | set-option -g wrap-search [on&rvbar;off] (default on) |
screenに慣れてるとtmuxでもコピーの完了時にSpace を押してしまってコピーできずにちょっと戸惑います。 まあ、そこは慣れですね。
特にscreenの矩形選択が分かり辛いので、 それに対するtmuxの方法は大分良い感じです。
tmuxのコピーモード時のキー設定は
: list-keys -t vi-copy
で見ることが出来ます。
また、Prefix Ctrl-[ でもコピーモードに入れる様なキーバインドを設定したいとき、 Ctrl-[はESCと同値なので、 tmuxの場合にちょっと注意が必要です。
tmuxではtmux自体でエスケープシーケンスを
解析する様な構造になってるらしく、
escape-time
という設定項目があります。
この設定はデフォルト500でms単位でエスケープシーケンスを待つ時間の設定になっています。 コピーモードに入りたいときに Prefix Ctrl-[で入ろうとすると、 この時間の分だけ一時的に待つのでちょっとタイムラグが有ります。
なので、これを
set-option -g escape-time 1
の様に最小値にしておきます。
もし必要なキー入力がある場合には、必要な場合、メタキー+keyの形で入力出来るように 設定しておきます。
screenではクリップボードは通常1つしか管理できませんが、 tmuxではデフォルトで複数クリップボードが管理できて過去のクリップボードを 再利用することが出来ます。
ただ、screenでもmulti_clipboard を使えば複数クリップボードを管理できます。
追記: 2015/01/04
両者とも、環境に応じてスクロールバックして戻れる行数を指定してあげることが出来ます。 特に、screenの方はデフォルトが100行だけなので普通に使うなら増やしておかないと不便です。
リソースが少ないサーバーとかで絶対負荷を掛けたくない、という場合を除いて 1万行くらいにしておいてもメモリの問題等は無いので大体それくらいに。
それから、screenの方はコピーモード時に検索でnで進んでいくと、 一番下まで行くと止まりますが、 tmuxの方はwrapモードがデフォルトで一番下まで行くと一番上の物に戻ります。
screenの方は設定変更はありませんが、tmuxではこれをwrap-search
というオプションでon/offしてあげる事ができます。
また、screenの方は1万行、と設定していると最初から1万行確保される様な形になっていて、 開いたばかりのWindowでも空白行が上に続いていて、 ggとかで一番上まで行くとずーっと空白行が続く空間に飛ばされます。
一方tmuxの方は実際に始まった所が最初になってるので、この点は tmuxの方が良い点です。
追記ここまで
Session/Layout/Window/Pane
screenとtmuxの違いの最大の点はWindow/Paneの意味の違いです。
screenではそれぞれのシェルが実行されてる領域はWindowと呼ばれます。 Windowはセッション全体で一括で管理されています。 (一応、Window GroupというWindowをグループ化して管理する機能もあります 2。) Windowは画面上に表示せずに隠しておくことも可能で、 また、分割された複数の領域に同時に表示することも可能です。
一方で、tmuxのWindowは表示される画面の事を言います。 各領域はPaneと呼ばれます。 Paneは各Windowに属していて、必ず何れかのWindowの中に表示される 必要があり、また、screenと違い同時に2つ表示する事は出来ません。
この違いから、tmuxの場合は、特に分割して使う場合、 基本的に一度Windowを作ったら 表示を変更したりせずにそのまま使う、と言うのが通常の使用方法になると思います。
screenの使い方が、割りとWindowを次々と入れ替えながら使ったりするので、 この違いがtmuxに移行が中々進まない最大の理由だったりします。 (逆にtmuxの感覚に最初に慣れてればscreenの感覚は足りない感じがするのでしょうが)
Layoutに関してはscreenの場合は自分で用意する必要がありますが 3、 tmuxに関しては予め幾つかレイアウトが用意されていて Prefix-Spaceでレイアウトを変更することが出来ます。
screenのレイアウトはWindowの表示位置や分割数もきちんと決まったものだったりしますが、 tmuxの場合はWindow内のPaneの数によって良しなに設定してくれます。
even-horizontal
というレイアウトは等間隔で横方向に並べ、
even-vertical
というレイアウトは等間隔で縦方向へ、
またtiled
という全てのPaneをなるべく同じような大きさに設定してくれる物もあります。
レイアウトに関してはtmuxの機能は結構優れてると思います。
また、tmuxで
一時的に一つだけ全体表示したい、みたいな事をしたいときに、
:break-pane
というコマンドで現在のPaneだけのWindowを別途作って
表示、みたいなことも出来ますがこの場合は元に戻す時には
元のWindowに戻って独立させたPaneを移動させて、みたいなことが必要になってしまいます。
コレに変わって、tmux1.8以降では、
:resize-pane -Z
というコマンドが用意されています。(デフォルトでPrefix zにバインドされてます。) これをすると、一時的に現在のPaneだけの表示になります。 もう一度Prefix zなどすれば元に戻ります。
最後にSessionに関してですが、
基本的には同じ様なものですが、
tmuxの方ではSessionの上にServerが動いていて、
全てのSessionはServerに管理されています。
このため、tmuxの方では1つのSessionの中からchoose-session
等で
直接他のSessionに移ることも可能です。
それからtmuxの方にはClientという概念もあって、 Sessionに接続している端末名(/dev/ttys001等)が管理されています。 これを使って端末ごとにdetachさせたりすることも可能です。
split
ちょっと前まではscreenの方はパッチを宛てないと縦分割出来ないような状態だったので それもtmuxの便利な点の1つでしたが 最新のものではtmuxもscreenも横分割も縦分割も出来るようになっています。
で、ここで少し混乱するのが、縦
(vertical
)分割と横
(horizontal
)分割の定義が
tmuxとscreenで逆なことです。
screenの方は縦分割(:split -v
)は縦方向に線が入る様な分割、
tmuxの方は縦分割(:split-window -v
)は縦方向に並べる様な分割。
Vimなんかだと:vsplit
はscreenの様に縦方向に線が入って横に並べる様な表示です。
screenではPrefix S等を横分割、
Prefix V等を縦分割にしていましたが、
この動きと合わせるためにはtmuxでは逆に
Prefix S等を縦分割(:split-window -v
)、
Prefix V等を横分割(:split-window -h
)にする必要があります。
全Paneに同時入力
tmuxを使いたい理由になる機能の1つ。
:set-window-option synchronize-panes on
をすると現在のWindowにある全てのPaneに対して同時に同じ キーを送る様になります。
複雑な作業を同時に行うのはあれですが、
サーバー管理等で複数端末にshutdown
コマンドなど簡単なコマンドを送りたいとき
なんかは便利です。
:set-window-option synchronize-panes off
とすると解除されます。
swap-paneの問題
tmuxでPaneを他のWindowへ送ったり移動させたりする
swap-pane
というコマンドがあるのですが、
これが現行の安定バージョンの1.9aの場合、
[lost server]
と出て落ちてしまう事があります。
スワップしようとするPaneがある2つWindowの何方かが Paneが1つしかない場合にこの現象が起こる様。
開発版の方の2.0を入れるとこの現象は起こらないので、
swap-pane
を多用する場合は2.0が必須です。
開発版はMacだとHomebrewで
$ brew install tmux --HEAD
で入れる事が出来ます。
Linuxなどだと直接Gitレポジトリから取ってきてコンパイルする必要がありますが、 automake等、全てローカルに自分でコンパイルして入れてる場合、 少し面倒があったので注意が必要です。
Status表示
screenの方はこちら参照。
tmuxの方は各Pane毎のcaptionの様な物は無く、 全体のstatusラインだけがあります。 また、screenではコマンド表示用のラインは別途一行用意されますが、 tmuxではコマンド/結果の表示はstatusライン上になります。
tmuxのstatusラインでは、真ん中にWindow情報、 さらに左側と右側に別途情報が載せられる様に設定出来ます。
set-window-option -g window-status-format "window info"
set-window-option -g window-status-current-format "current window info"
set-option -g status-left "left info"
set-option -g status-right "right info"
の様な設定。Window情報は現在のWindowとその他で表示を変えられます。
Window情報はPaneの新規作成等、Windowの状況が変わるたびにアップデートされます。
一方、left/rightの方はstatus-left-length
/status-right-length
で指定された秒数毎にアップデートされます。(デフォルトは15秒)
left/rightの中では#()
を使って通常のシェルコマンド等を指定することも出来、
length
で指定された間隔毎にコマンドを実行して結果を表示できます。
これによってかなり自由度が高い表示が可能になっています。
(Window情報では#()
形式でのコマンド指定は出来ません。)
ステータス表示ではプロンプト表示のPS1
への指定
の様に#h
で短縮ホスト名等を指定することも可能です。
また、tmux内の情報を#{window_panes}
の様に持ってくる事が出来る物もあります。
(詳しくはman tmux
のFORMATS
の項目で。)
ステータスラインの色指定は、全体を指定したい場合は
set-option -g status-style "bg=colour236,fg=black,bold,underscore"
とstatus-style
を設定します。
fg/bg両方指定したい場合は,
でつなげます。
left/right領域を別に設定したい場合には
status-left-style
/status-right-style
という設定項目もあります。
ここで、色指定には
black, red, green, yellow, blue, magenta, cyan, white
の8種類か、
colourN
(N=0-255)という形での色指定4、
または#ffffff
という16進法の指定も可能です。
(ただし、この場合全ての色が可能なわけでなく、256色使える端末なら
指定色に一番近い色が表示されます。)
色指定の所で注意なのがcolour255
みたいな指定をするときに、
アメリカ英語のcolor
ではなく、イギリス英語のcolour
の綴りになってる所。
tmuxのヘルプの中も通常のカラー、というところは全てcolour
になってます。
プログラムしてる中でcolour
を使ってるのは殆ど見たこと無いので
なんとなしに書くと間違えて色が変わらなくて戸惑います。
また、printf
を使ったりPS1
の値などでWindowのタイトルなどを変更できますが
以下の様な値で変更が出来ます。
screen | tmux | |
---|---|---|
\ek ~\e\134 |
Window title | Window Name |
\e]2; ~\a |
- | Pane title |
.bashrcなどでの判断方法
.bashrcなどでscreenやtmuxの中かどうかで設定を変えたい場合、
基本、両方共TERM
の値がscreen
になっているのでそれを使います。
1 2 3 4 5 6 7 |
|
また、screenとtmuxを区別したい場合には
tmuxの場合にはTMUX
という環境変数が設定されるので
1 2 3 4 5 6 7 8 9 |
|
みたいにすると判断できます。
(もしくはscreenの場合にはTERMCAP
の値が
SC|screen|VT 100/ANSI X3.64 virtual terminal:...
みたいな値になっています。
特に指定して無ければtmuxではこの値は指定されません。)
違いが理解できたら
上の違いを踏まえた上でtmuxをscreenの様に使えるようにカスタマイズしてみます。 (ならscreenを使え、というのはなしで)