2011/12/18

開発版GNU Screenで楽々ウィンドウ管理

本記事は ターミナルマルチプレクサ Advent Calendar 2011 : ATND の18日目です。17日目は tmux ♡ ssh な生活 - 林檎パーク でした。設定によって ssh する操作を加速できるのはターミナルマルチプレクサの強みの一つですよね。それでは 14日目の記事 の続きとして開発版 GNU Screen におけるウィンドウ関連の変更点について説明します。

足りない、ウィンドウ

足りない、ウィンドウ 皆さんは GNU Screen をどのようにお使いになっていますか?

私の例を紹介しますと、ある特定のハブホストに ssh して screen を起動し、そこから複数のリモートサーバにログインして各種コマンド作業やログ、負荷の監視などで使用しています。

ところが対象となるサーバが増えてくると、それに応じた数のウィンドウを作成しますので 40 個では足りない場合が出てきます。この数の壁が作業する上で支障となりましたので回避策を探したことがあります。

  • screenで40より大きな番号を設定する方法
    ウィンドウ番号が一桁のものは「C-a ウィンドウ番号」と簡単にアクセスできますので、私はそれらを頻繁に利用するウィンドウ用として空けておきたいので、10番以降を用途別、たとえばWebサーバは10番台、DBサーバは20番台等と決めて作業していますが、デフォルトではウィンドウは40までしか作成できず、私の今の用途ではちょっと足りません。
単に CFLAGS に -DMAXWIN=100 を指定してコンパイルしただけですが、ウィンドウ番号の幅が広がり作業がより快適に行えるようになりました。

そもそもこれだけの数ログインしっ放しなのか?という向きもあるかも知れませんが、基本的に監視で使っているウィンドウ以外は作業後にログアウトしています。zombie kr と設定していますので :screen -t websvr2:2 14 ssh user@websvr2 などとして作成したウィンドウはログアウトしても残ります。これにより次回以降のログインは r キーのみで速やかに行えます。

このように基本的に一度割り当てたウィンドウは使い回すようにしていますので、使用できるウィンドウ番号の幅が広がるというのはとてもありがたいです。

開発版 GNU Screen ではこの最大ウィンドウ数の初期値は 100 に広がり、2048 までは設定 maxwin で変更できます。

この数値はウィンドウを管理する配列の初期化に使われているようですので、変更はウィンドウを生成する前に行う必要があります。また一度設定すると減らすことしか出来ません。とはいえ、これでウィンドウの数には悩まなくて済みそうです。

ウィンドウをグループで整理する

しかしながら多数のウィンドウを扱うようになると番号でルールづけしていたとしても windowlist での見通しはよくありません。それに 10 番台は〜、20 番台は〜、という割り当てでは、そのカテゴリに属しているウィンドウの数が増えてきて番号がズレたときに悲しい思いをします。事実上ウィンドウ数の制限は無くなりましたのでカテゴリ間のウィンドウ数を 20 に増やすなど運用で回避していましたが、その脳内管理にも無理が出てきます。

そのようなケースにはウィンドウグループの使用が適しています。どのように使うかは以前まとめた記事がありますのでそちらをご覧ください。(コレばかりでスミマセン。。。)

冒頭にあげた使用例をウィンドウグループを使った場合にどうなるのかを示したのが次の図です。 ここでは説明のため、領域を縦に3分割、さらに右を上下に2分割して合計4つの領域を表示しています。

  1. 左は、ウィンドウ8(other)を表示しているときに windowlist を実行した状態
  2. 真ん中は、(1) で g を押して配下のグループを展開した状態
  3. 右上は、(1) でウィンドウ100(Web/)を選択した状態
  4. 右下は、(1) でウィンドウ700(Test/)を選択してから g を押した状態
個別のウィンドウ作成部分を除いたウィンドウグループ生成に関する設定は次のようになります。ウィンドウグループは一目でそれと分かるように、名前の末尾に / を付けています。スクリーンショットの見栄えを強調するため、新設された rendition もついでにいくつか定義しています。
caption always '%?%F%{= gW}%:%{= Kk}%?%2n%f%07=%t%='
hardstatus alwayslastline '[windowgroup sample]%L=%-w%45L>%{= gW}%n %t%{-}%+w%{-}%-33<%=screen 4.01.00devel (GNUa805439)'

windowlist title '%{u .g} Num Flags Title%='
windowlist string '%4n %{.y}%f%09=%{-} %t %='

rendition so      '=' 'gW'
rendition bell    '+' '.y'
rendition silence '+u'

select -
screen -t Web/     100 //group
# ウィンドウグループ(Web/)属するウィンドウを生成

select - # ウィンドウグループを抜ける
screen -t DB/      500 //group
# ウィンドウグループ(DB/)に属するウィンドウを生成

select -
screen -t Test/    700 //group
screen -t TestWeb/ 700 //group
# ウィンドウグループ(TestWeb/)に属するウィンドウを生成

select Test/ # ウィンドウグループ(Test/)を選択
screen -t TestDB/  750 //group
# ウィンドウグループ(TestDB)に属するウィンドウを生成
select -

ただ困ったことに、今回のスクリーンショットを取るときに気づいた点が2つあります。一つ目は、windowlist でグループを展開しているときに、イベント(bellsilencemonitor)の発生したウィンドウがあると階層構造が崩れて表示されてしまうことです。そのような時は何度か g を押してウィンドウグループの開閉を繰り返して再描画させれば表示は元に戻ります。

もう一つはかなり深刻で、monitoron にしているウィンドウがある状態で入れ子のあるウィンドウグループを選択したり、windowlist を表示するときに、その monitor イベントが起こるとほぼ確実に screen がクラッシュします。残念ながらこの問題が修正されるまでは開発版 GNU Screen で monitor の使用は控えた方が良いと思います。

ssh コマンドをキーバインドで呼びだす

自由に割り振ることの出来るウィンドウ番号と、それら複数ウィンドウをカテゴライズできるウィンドウグループを使う事で screen の利便性はかなり上がります。しかし属させたいウィンドウごとに :group Test/ などと入力しなければいけませんし、現在操作しているウィンドウグループ内で新たに作成したウィンドウはそのグループに属することになりますのでその動きが嬉しくないときもあります。

まともに tmux を使ったことが無いのですが前日(17日目)の iwatam さんの記事で言及されている点は同意します。GNU Screen は優れたコマンドランチャとしても使えますので、それと組み合わせることでウィンドウグループの設定も手軽にできます。

みなさんは開発環境やら、本番環境やらにsshで入ってほげほげするあれげな人ばっかりだと思うのですが、大体sshするときって別window使ったり、paneを切ってやったりしますよね? でもわざわざnew-windowやったり、split-paneしてからsshとかってダサくてキモいですよね。 なので、.tmux.confに以下のような設定をしてその辺一発でできちゃうようにしましょう。

私は複数あるサーバに ssh し易いよう、以下のような感じでランチャ風に多段キーバインドを定義しています。

# alias for remote login
# override default `^V'(digraph) mapping
bind ^V eval 'command -c rlogin' 'echo "select server category: [0]  [1]Web [2] [3] [4] [5]DB [6] [7]Test [8] [9]"'
bind -c rlogin 1 eval 'command -c rlogin1' 'echo "login to: (1 Web)  [1]websvr1 [2]websvr2"'
bind -c rlogin 5 eval 'command -c rlogin5' 'echo "login to: (5 DB)   [1]dbsvr1  [2]dbsvr2"'
bind -c rlogin 7 eval 'command -c rlogin7' 'echo "login to: (7 Test) [1]testweb [5]testdb [6]testdb2"'

# (1 Web/)
bind -c rlogin1 1 eval 'screen -t websvr1 11 ssh websvr1' '@group Web/'
bind -c rlogin1 2 eval 'screen -t websvr2 13 ssh websvr2' '@group Web/'
bind -c rlogin1 3 eval 'screen -t websvr3 16 ssh websvr3' '@group Web/'

# (5 DB/)
bind -c rlogin5 1 eval 'screen -t dbsvr1 51 ssh dbsvr1' '@group DB/'
bind -c rlogin5 2 eval 'screen -t dbsvr2 55 ssh dbsvr2' '@group DB/'

# (7 Test/)
## (7 Test/TestWeb/)
bind -c rlogin7 1 eval 'screen -t testweb 701 ssh testweb' '@group TestWeb/'

## (7 Test/TestDB/)
bind -c rlogin7 5 eval 'screen -t testdb 750 ssh testdb' '@group TestDB/'
bind -c rlogin7 6 eval 'screen -t testdb2 755 ssh oracle@testdb2' 'encoding eucjp' '@group TestDB/'
この例では、Ctrl-A Ctrl-V 1 2 とすることでウィンドウグループ Web/ に属したウィンドウで websvr2 に ssh します。ブログ幅の都合上、スペース部分を一部省いていますが、.screenrc 上では数字の桁を固定幅で揃えておくと見やすいです。group の前に @ を付けているのは、ウィンドウグループ設定時のメッセージ window group is 100 (Web/) を抑止するためです。(これも新機能)他にも接続先サーバによっては encodingstuff を使って初期値をあらかじめ設定するということも出来ます。eval で連続して実行させるのがポイントです。

ウィンドウを素早く整理する

最後にウィンドウグループ以外のウィンドウ関連の変更として、windowlist の変更点をいくつか紹介します。細かな変更点は以前まとめた記事をご覧ください。

ウィンドウ番号の交換

先に挙げたランチャ設定で作業していると、既に作成しているウィンドウがあるためにウィンドウ番号が連続せずにもどかしい思いをすることがあります。そのようなときは , を何回か押しましょう。

, , ,
押しすぎてしまった場合は落ち着いて . を何回か押しましょう。下の番号と入れ替わります。

ウィンドウの削除

ウィンドウリスト上で K を押すことにより該当ウィンドウを直接 kill できます。これにより不要に作りすぎたウィンドウの消去が楽に出来ます。

k
k
k
k
K
y

ウィンドウ名の前方一致検索

ウィンドウリスト上で / を押すとプロンプトが表示されます。そこに検索文字列を入力して Enter すると該当するウィンドウが選択されます。続けて n を押すと次の候補が選択されます。N で逆順に検索します。

n
この検索はかなり使えます。いままでのウィンドウリストでは jk の行単位か Ctrl-FCtrl-BCtrl-DCtrl-U などの1ページ、半ページ単位の移動しかできませんでしたが、現在はウィンドウが数十あったとしてもピンポイントに検索・選択できます。欲を言えば部分一致でも良かったかなと思います。

おわりに

多数のサーバに ssh する私の例が適切かどうか分かりませんが、ウィンドウ関連の変更点についてご理解頂けましたでしょうか?ウィンドウグループはともかく、最後に紹介した windowlist の操作だけでも開発版 GNU Screen による利便性を享受できるのではないかと思います。

0 件のコメント:

コメントを投稿