前提
ターミナルマルチプレクサとは、
- GNU screen
- tmux
などの仮想端末マネージャのことです。
メリット
- マウスを使わず端末内でコピペできる(スクロールバックで端末画面外に流れてしまった情報にアクセスできる)
- アタッチ・デタッチ機能で一時停止ができる
- 画面分割により、一画面でコマンドラインとエディタを表示できる
- 画面管理もできるので、すべてのウィンドウをタブのように管理できる
- すべて設定ファイルでカスタマイズできる
ことが挙げられます。デメリットとしては、Vim や Emacs にように初期の導入コストが高いことでしょうか。これらの類はとっつきにくいイメージが有りますが、エディタのそれよりは簡単です。
参考
こんな感じ
これが普段使いの環境です。私の場合ですが、OS X 10.10
で利用し、インストールは Homebrewからです。ターミナル.app をフルスクリーンモードにして、その中で tmux から画面を分割したり束ねたりして利用しています。
$ tmux -V
tmux 1.9a
少し解説を入れます。
私はモバイル機・デスクトップ機ともに OS X なので、目の動きを同じにするためにステータスバーは上部に配置しています(これは Linux ユーザにも言えるかも)。
さらに、私は大画面で開発したいので、ターミナル.app をフルスクリーンモードで利用しているのですが、それゆえに OS X のステータスバーが隠れてしまいます。これでは、現在時刻や Wi-Fi やバッテリ残量なども確認できないので、専用スクリプトを書いて tmux 上のステータスバーに表示できるようにしています。
set-option -g status-right '#(get_ssid) #(battery -c tmux) [%Y-%m-%d(%a) %H:%M]'
get_ssid
これは、Wi-Fi の SSID を取得するスクリプトです。ここからダウンロードし、実行権限(chmod 755 get_ssid
)をつけてパスの通ったディレクトリ(例:/usr/local/bin
)にインストールしてください。※現在、Mac のみ対応
battery -c tmux
これは、バッテリー残量を取得するスクリプトです。残量を 時:分
と パーセンテージで表示します。ここからダウンロードし、get_ssid
と同様にインストールしてください。battery
はオプションなしで実行すると色はついていません。-c tmux
とすることで、tmux 用のカラーがオンになります。※Mac 完全対応、Linux 一部対応
- 緑:充電中
- 青:20% 〜 100%(緑 100% になると Full charged と表示され青くなる)
- 赤:1% 〜 19%
ちなみに、ステータスバーを上部に配置できるようになったのは tmux 1.7からです。
ステータスバー
上で挙げたカスタマイズ例を設定ファイルから見てみます。
# ステータスバーをトップに配置する
set-option -g status-position top
# 左右のステータスバーの長さを決定する
set-option -g status-left-length 90
set-option -g status-right-length 90
# #H => マシン名
# #P => ペイン番号
# 最左に表示
set-option -g status-left '#H:[#P]'
# Wi-Fi、バッテリー残量、現在時刻
# 最右に表示
set-option -g status-right '#(get_ssid) #(battery -c tmux) [%Y-%m-%d(%a) %H:%M]'
# ステータスバーを Utf-8 に対応
set-option -g status-utf8 on
# ステータスバーを1秒毎に描画し直す
set-option -g status-interval 1
# センタライズ(主にウィンドウ番号など)
set-option -g status-justify centre
カラースキーム
上記画像で見せた環境は Terminal.app 上で tmux、(zsh、)vim です。すべてカラースキームは Solarizedで統一しています。Solarizedは低コントラストで視認性もよく飽きがこないお勧めカラースキームです。
簡単にそれぞれの設定方法を紹介しておきます。
Terminal.app
上記リンク先から Dark または Light をダウンロードする。Command+,
で環境設定を開き、「歯車マーク」>読み込む...
から先ほどダウンロードした .terminal
ファイルを読み込めばオッケー。
tmux
上記リンク先にカラースキームの dark と light があるので、好きな方を ~/.tmux.conf
にコピペするだけです。
Vim
NeoBundle ユーザは以下を ~/.vimrc
に記述するだけです。
NeoBundle 'altercation/vim-colors-solarized'syntax enable
setbackground=dark"または lightcolorscheme solarized
プラグインマネージャを使用していない場合は以下です。
$ git clone https://github.com/altercation/vim-colors-solarized
$ cd vim-colors-solarized/colors
$ mv solarized.vim ~/.vim/colors/
そして、~/.vimrc
に以下を記述します。
syntax enable
setbackground=dark"または lightcolorscheme solarized
コピーモード
tmux の魅力の一つのコピーモードです。コピーモードは端末上でマウス操作を一切なしでコピペできる優れ機能です。また、デフォルトでは 2000 行までのスクロールバック(端末画面外に消えてしまった出力)をさかのぼれます(Ctrl-f
、Ctrl-b
)。
このコピーは tmux のバッファスタックに保存されます。つまり、OS のクリップボードと連携できません。では、さっそく連携させましょう。
# Vi キーバインド
set-window-option -g mode-keys vi
# Prefix+v でコピーモード開始
bind-key v copy-mode \; display "Copy mode!"
#bind-key -t vi-copy v begin-selection
# Prefix+Enter/y でコピー
bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"
bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"
# Prefix+p でペースト
# クリップボードにも保存されているので Cmd-v でもペースト可能
bind-key p paste-buffer
これは Enter
/y
押下時に reattach-to-user-namespace pbcopy
を実行しています。pbcopy
は OS X ターミナル上からクリップボードを利用するコマンドですね。reattach-to-user-namespace
はそれの橋渡し的存在です。Homebrewユーザなら、
brew install reattach-to-user-namespace
で OK です。
ちなみに copy-pipe
は tmux 1.8 から利用可能です。それ以前はとてもややこしい方法で実現させていました。
また、Vim とでも tmux のコピペができると便利なので連携させましょう(参考:tmuxとMacのクリップボードを共有する(copy-mode, vim))。
# vim <=> tmux 間でクリップボード利用を可能にする
set-option -g default-command "reattach-to-user-namespace -l $SHELL"
以前はスクロールバック用のモードがあったのですが、今はコピーモードに統合されました。なので、コピーモードのキーバインドをカスタマイズすれば、カーソル移動やページめくりが便利になります。
# Esc キーでコピーの反転を解除(コピーモードは抜けない)
bind-key -t vi-copy Escape clear-selection
# Ctrl-c キーでコピーの反転を解除し、コピーモードから抜ける
bind-key -t vi-copy C-c cancel
# コピーモード中(Prefix+v 後)C-v で矩形選択開始
bind-key -t vi-copy C-v rectangle-toggle
# 1行選択
bind-key -t vi-copy V select-line
# Vi モード中に Ctrl-a で行頭に(Emacs ライク)
bind-key -t vi-copy C-a start-of-line
# Vi モード中に Ctrl-e で行末に(Emacs ライク)
bind-key -t vi-copy C-e end-of-line
# 単語の最初の1文字に移動
bind-key -t vi-copy w next-word
# 単語の最後の1文字に移動
bind-key -t vi-copy e next-word-end
# w の逆の動き back
bind-key -t vi-copy b previous-word
# 画面上に映る最上行に移動
bind-key -t vi-copy g top-line
# 画面上に映る最下行に移動
bind-key -t vi-copy G bottom-line
# 前方検索
bind-key -t vi-copy / search-forward
# 後方検索
bind-key -t vi-copy ? search-backward
# ページスクロール
bind-key -t vi-copy C-n page-up
bind-key -t vi-copy C-f page-down
# ページ送り
bind-key -t vi-copy C-u scroll-up
bind-key -t vi-copy C-d scroll-down
ペイン・ウィンドウ操作
tmux はペインでウィンドウを分割でき、開発内容や案件ごとにウィンドウを保持し、サーバーごとにセッションを管理できます。
ペイン | ウィンドウ | セッション | クライアント |
---|---|---|---|
ウィンドウを分割した領域 縦分割、横分割 | タブのようなもの ペインを管理する領域 | ウィンドウの集まり を総称したもの | tmux を起動している ターミナルや端末のこと |
これらの切り替えをスムーズにする設定をしましょう。ペインやウィンドウの切り替えは vi ライクなキーバインドにしています。コピーモードでも vi ライクなものにしているので統一しておくのがいいでしょう。
# ウィンドウとペインの番号を1から開始する(デフォルト0)
set-option -g base-index 1
set-window-option -g pane-base-index 1
# Prefix+- で横に、Prefix+| で縦に分割(ペイン)する
bind-key | split-window -h
bind-key - split-window -v
# Prefix + Ctrl-h/l でウィンドウ切り替え
# Prefix + Ctrl-h,h,h,h,...と連打できる
bind-key -r C-h select-window -t :-
bind-key -r C-l select-window -t :+
# Prefix+hjkl でペイン移動
bind-key h select-pane -L
bind-key j select-pane -D
bind-key k select-pane -U
bind-key l select-pane -R
# ペインサイズを上下左右(Prefix+JKHL)に変更
# Prefix+J,J,J,J,...と連打してリサイズ可能
bind-key -r H resize-pane -L 5
bind-key -r J resize-pane -D 5
bind-key -r K resize-pane -U 5
bind-key -r L resize-pane -R 5
# Ctrl-o でペインをローテーションしながら移動
# Prefix を用いないのでタイプが楽だが、Ctrl-o を使用してしまう
# 他のソフトウェアの設定に支障をきたさないように注意
bind-key -n C-o select-pane -t :.+
シェルと連携する
さあ、ここまで来ると便利さがわかってきた tmux。しかし、このままではシェルとの連携ができていません。つまり、シェルにログインした時(ターミナル.app を再起動した時など)、いちいち
$ tmux
としないと、tmux に入れません。これでは非常に面倒なので、シェルにログインした時にデタッチされたセッションに自動にアタッチ出来るようにしましょう。tmux では Prefix+d
で明示的にデタッチもできますが、端末が終了したとき(ログインシェルで exit
した時や、Command+q
でターミナル.app を終了した時)にも自動でデタッチされます。
よって、シェルにログインした時に、デタッチされたセッションがあればアタッチし、なければ tmux new-session
を実行するようにしてみましょう。
function is_exists(){type"$1">/dev/null 2>&1;return$?;}function is_osx(){[[$OSTYPE== darwin* ]];}function is_screen_running(){[ ! -z "$STY"];}function is_tmux_runnning(){[ ! -z "$TMUX"];}function is_screen_or_tmux_running(){ is_screen_running || is_tmux_runnning;}function shell_has_started_interactively(){[ ! -z "$PS1"];}function is_ssh_running(){[ ! -z "$SSH_CONECTION"];}function tmux_automatically_attach_session(){if is_screen_or_tmux_running;then
! is_exists 'tmux'&&return 1
if is_tmux_runnning;thenecho"${fg_bold[red]} _____ __ __ _ ___ __ ${reset_color}"echo"${fg_bold[red]}|_ _| \/ | | | \ \/ / ${reset_color}"echo"${fg_bold[red]} | | | |\/| | | | |\ / ${reset_color}"echo"${fg_bold[red]} | | | | | | |_| |/ \ ${reset_color}"echo"${fg_bold[red]} |_| |_| |_|\___//_/\_\ ${reset_color}"elif is_screen_running;thenecho"This is on screen."fielseif shell_has_started_interactively && ! is_ssh_running;thenif ! is_exists 'tmux';thenecho'Error: tmux command not found' 2>&1
return 1
fiif tmux has-session >/dev/null 2>&1&& tmux list-sessions | grep -qE '.*]$';then# detached session exists
tmux list-sessions
echo -n "Tmux: attach? (y/N/num) "readif[["$REPLY"=~ ^[Yy]$ ]]||[["$REPLY"=='']];then
tmux attach-session
if[$? -eq 0];thenecho"$(tmux -V) attached session"return 0
fielif[["$REPLY"=~ ^[0-9]+$ ]];then
tmux attach -t "$REPLY"if[$? -eq 0];thenecho"$(tmux -V) attached session"return 0
fififiif is_osx && is_exists 'reattach-to-user-namespace';then# on OS X force tmux's default command# to spawn a shell in the user's namespacetmux_config=$(cat $HOME/.tmux.conf <(echo'set-option -g default-command "reattach-to-user-namespace -l $SHELL"'))
tmux -f <(echo"$tmux_config") new-session &&echo"$(tmux -V) created new session supported OS X"else
tmux new-session &&echo"tmux created new session"fififi}
tmux_automatically_attach_session
上記コードを ~/.bashrc
なり、~/.zshrc
なりに貼り付ければいいです(それ以外のシェルでは動作未確認)。
では簡単にどんな動きをするか解説します。
- ターミナルマルチプレクサが既に動いていたら、その旨を出力する(tmux に関しては AA を表示している)
- screen や tmux 上でなく、ssh 接続先でもなくインタラクティブシェルとして起動されたログインシェルなら以下に分岐する
- デタッチされたセッションがある場合
y
またはEnter
が入力された場合:最後にいたセッションにアタッチする- 数字が入力された場合:その数字のセッション番号のセッションにアタッチする
- それ以外が入力された場合:新規セッションを作成
- デタッチされたセッションがない場合
- 新規セッションを作成
- デタッチされたセッションがある場合
とりあえず、最後のセッションにアタッチしたけりゃ Enter
で問題無いです。
最後に
ターミナルマルチプレクサはターミナル生活を豊かにします。今回は tmux を題材にその周辺環境を含めて紹介してみました。本記事で載せた tmux に関するコードはすべてここにあります。コピペして ~/.tmux.conf
に配置し再読み込みすれば利用できるはずです。需要があれば以下の設定方法も追記しようと思います。
- ログイン時に tmux 自動起動されるが、これに自動画面分割の処理も加える
- 別のペイン/ウィンドウのカレントディレクトリに移動する
SEE ALSO