2010/11/03

そんな.screenrcで大丈夫か?

GNU Screen を使い始めて4年ほど経ちましたが、雑誌、書籍、ネット上での先駆者の設定を大して意味も理解せずコピペして肥大化してきました。来るべきバージョン4.1の正式リリースに備えて、ここで今一度自分の .screenrc を確認してみようと思います。

タイトルは釣りです。勢いでつけました。すいません。

まずは現在の MacBook で使用している設定を貼り、個別に解説していきます。意味の通らないコメントが多いと思いますが気にしないでください。設定ファイルはメインとなる .screenrc とホスト個別の .screenrc.local の2つあります。後者はシンボリックリンクでホストごとに管理しています。このへんは良くある構成だと思います。



それでは上から順番にいきましょう。

# Escape key is C-t, literal is a.
escape ^Ta

これは screen のコマンドを実行するためのトリガとなるキーの設定です。デフォルトでは Ctrl-A に割り当てられていますが、これは Readline のキーとかぶっていて使い勝手がよろしくないので Ctrl-T に替えています。2文字目の a は、コマンドキー自身(この場合は Ctrl-T )を送る場合に指定するキーです。なぜか a にしていますが、私は通常の CUI 作業でほとんど Ctrl-T を使わないので深い意味はありません。何も考えずに man にある設定をコピペって ^T に替えただけなんだろうと思います。便宜上、以下の解説ではデフォルトの Ctrl-A として進めます。

# I like a large scrollback buffer.
defscrollback 1000

生成されるウィンドウのデフォルトスクロールバックバッファの行数を指定します。初期値は 100 らしいので、それではあんまりなのでこの値にしています。私は多数のウィンドウを生成する事が多いので控えめにしています。流れてしまっては困るときはログを取るなり scrolllback num で一時的に大きくしたりします。

# clear scrollback buffer
bind F eval 'scrollback 0' 'scrollback 1000' 'echo "scrollback buffer cleared"'

スクロールバックバッファをクリアするキーを定義しています。クリアと言っても、単に一度行数を0にして戻してるだけです。あまり使いませんけど空いている F に割り当てときました。(いちおう Flush のつもり)

# don't show startup message.
startup_message off

書いてある通りです。:p

# don't remove windows from the window list as soon as window process exits.
zombie kr #  k: destory window, r: resurrect window

いつも邪魔者扱いされるゾンビですが screen においては頼りになる存在です。screen が生成したウィンドウ下のプログラム(たいていはシェル)が終了した場合にそのウィンドウを消さずに残す設定です。1番目の文字で「死んだ」状態のウィンドウを削除するキーの指定、2番目の文字でそれを復活(再実行)させるキーを指定します。

再実行は地味に便利です。リモートホストに接続するウィンドウを生成する場合、screen -t hogeserver 12 ssh hogeserver などと ssh コマンドを screen から実行すると思いますが、zombie を設定しておくと ssh 切断後もそのウィンドウは残ります。そこで r を押すことによりウィンドウ生成時のコマンド(この場合は ssh hogeserver)が再実行されます。打鍵数削減ですね。また、不慮の事故などで ssh 切断などに見舞われた場合でもウィンドウは残りますので wall によるメッセージなどが確認できます。

# echo command name whenever a window is created or resurrected.
verbose on

ウィンドウ生成/破棄時のメッセージを出すかどうかの設定。zombie と組み合わせるとよいと思います。

# changes the name of logfile.
logfile 'screen/log/screenlog.%H.%Y%m%d-%02c:%s-%n.%t.log'
logtstamp on
logtstamp string "\n-- SCREEN [%Y/%m/%d %02c:%s] %n:%t --\n"

ログファイルに関する設定。logfile path でログファイル出力先のパスを指定します。ファイル名のエスケープ文字については screen(1) の STRING ESCAPES を見てください。だいたい見たとおりです。私は screen をホームディレクトリから起動するのでそこからの相対パスを記述しています。パスには環境変数を指定することも出来るようです。存在しないディレクトリを設定してしまうとログ取得開始時に悲しい思いをします。

logtstamp on を指定すると、logtstamp after [secs] で指定した時間ウィンドウへの出力が無い場合、ログファイルにタイムスタンプ文字列(logtstamp string)を追記してくれます。長時間に渡る処理の標準出力など、タイムスタンプで進捗具合を測るときに役立つことがあります。

# changes the directory for hardcopy.
hardcopydir 'screen/hardcopy'
hardcopy_append on

ハードコピーに関する設定。hardcopydir dir でハードコピー出力先ディレクトリを指定します。例によって私の場合は screen を起動するホームディレクトリからの相対パスです。hardcopy_append onhardcopy 実行時にハードコピーファイルを上書きするのではなく追記するようにします。

# changes the filename used for reading and writing with the paste buffer.
bufferfile 'screen/screen-exchange'

bufferfie path でペーストバッファの内容をファイルに出力する際のファイル名を指定します。このコマンド自身は path に指定したファイルの内容をペーストバッファに読み込む役目もありますが、あまり使ったことがありません。screen のペーストバッファと OS のクリップボードを共有する際の中間ファイルとして指定することが多いと思います。

# changes the kind of messages to the nethack-style.
nethack on

screen の出力するメッセージを NetHack 風にする設定です。好みの問題です。コンパイルオプションによっては使えない場合もあるらしいです。どんなメッセージに変わるのか興味のある方はソース(src/nethack.c)を見てください。

# enable visual vells
vbell on

ビジュアルベルを有効にする設定です。

# disables vbell toggle binding to use ^G as cancel.
bind ^G

私はビジュアルベルの有効/無効を切り替えることはまずないので、デフォルトで Ctrl-G に割り当てられているビジュアルベルのトグルを無効にします。副次的に Ctrl-G を押しても何も起きなくなりますので、Emacs のキャンセルコマンドのように使えます。

# window re-numbering
# override default `N'(number) mapping
bind N colon 'number '

デフォルトで N に割り当てられている number はウィンドウ番号を表示するだけでありがたくも何ともないので、ウィンドウ番号を変更するキーにしています。(「Ctrl-A N」したあとに変更したい数字を入力するだけ)

# shortcut of screen sub-command with title option.
bind s colon 'screen -t '

screen -t と入力するためのショートカットを空いていた s に割り当ててみました。title をつけてウィンドウを生成するような用途は、現在だと後述するランチャで行っているのであまり使っていません。リストラ候補。

# switch window encoding
bind ^U eval 'encoding utf8'  'info'
bind ^E eval 'encoding eucjp' 'info'

# switch window encoding and changes LANG environment variable.(for b-shell)
bind u eval 'encoding utf8'  '!!!echo "LANG=ja_JP.utf8; export LANG"'  'info'
bind e eval 'encoding eucjp' '!!!echo "LANG=ja_JP.eucJP; export LANG"' 'info'

ウィンドウの文字コードを変換するキーを割り当てています。あとの2行は表示する文字コードを変えつつ、Bシェル向けの LANG 環境変数を変更するコマンドをウィンドウに送信しています。Cシェルな人は setenv 等に書き換える必要があります。ウィンドウ内がシェル入力待ち状態じゃないと悲しい思いをします。「!」が3つある理由はよく分かりません。コピペですごめんなさい。sjisとかも設定できますが私は普段あまり使わないので、よく使う UTF8 と EUC-JP を割り当てています。

# switch focus to other region(like vi)
# orverride default `k'(kill), `t'(time), `b'(break) mappings.
bind j focus down
bind k focus up
bind t focus top
bind b focus bottom

ウィンドウを分割している時にフォーカスを移動するためのキーを vim 風に割り当てています。いくつかデフォルトの割り当てを上書いていますが、私はどれも使わないので気にしません。

# continuous switch focus to other region(like vi)
bind ^J eval 'focus down' 'command -c cfocus'
bind ^K eval 'focus up'   'command -c cfocus'
bind -c cfocus ^J eval 'focus down'   'command -c cfocus'
bind -c cfocus ^K eval 'focus up'     'command -c cfocus'
bind -c cfocus ^T eval 'focus top'    'command -c cfocus'
bind -c cfocus ^B eval 'focus bottom' 'command -c cfocus'

上記と同じようなフォーカスを移動するためのキーの割り当てですが、フォーカスの上下移動(Ctrl-A Ctrl-[JK])をトリガとしてフォーカス移動モード(仮称)に移行してフォーカス移動キーの連続入力を受け付けるようにしています。3つ以上の領域に分割している場合など「2つ上に行きたい!」というときに「Ctrl-A k」を2回打つ代わりに「Ctrl-A Ctrl-K Ctrl-K」とできます。Crtlキーを押しっぱなしというのがポイントです。ただしその後も入力受付け状態は続いていますので、入力を受け付けていないキー、あるいは Ctrl-G 押すなりしないとフォーカス移動後のウィンドウに対する操作はできません。入力受付中かどうかを意識する必要はありますが、フォーカスの移動が苦にならなくなります。

# swap region to neighbour's
# orverride default `W'(width) mapping.
bind W eval 'command -c swap' 'echo "swap region to: [N]ext [P]rev"'
bind -c swap N eval 'select -' 'focus down' 'other' 'focus up'   'other' 'focus down'
bind -c swap P eval 'select -' 'focus up'   'other' 'focus down' 'other' 'focus up'

分割しているときに隣接するウィンドウの内容を入れ替えます。「Ctrl-A W」で入力プロンプトを出して、N で下のウィンドウ内容を上に、Pで上のウィンドウ内容を下に表示します。あまり使いません。eval によるコマンドを試したいだけだったような気がします。

# continuous resize region
# orverride default `r'(wrap) mapping.
bind r eval 'command -c cresize'
bind -c cresize j eval 'resize +1'  'command -c cresize'
bind -c cresize k eval 'resize -1'  'command -c cresize'
bind -c cresize J eval 'resize +10' 'command -c cresize'
bind -c cresize K eval 'resize -10' 'command -c cresize'
bind -c cresize = eval 'resize ='   'command -c cresize'
bind -c cresize n eval 'resize min' 'command -c cresize'
bind -c cresize x eval 'resize max' 'command -c cresize'

分割している領域をリサイズする設定です。「Ctrl-A r」でリサイズモード(仮称)に移行します。続けて「j」を押せば1行広がります。「jj」と押せば2行広がります。大文字の「J」を押すと 10行広がります。この設定も入力状態が続くようにしていますので、7行広げたければ「Ctrl-A r jjjjjjj」や「Ctrl-A r Jkkk」などとできます。ちなみに「n」にすると1行になります。急いで小さい領域にリサイズしたければ「Ctrl-A r njjj」などとします。意図したサイズになったら Ctrl-G 等で入力待機状態をキャンセルします。topコマンドなど画面を描画中のものがある最中に連続してリサイズしてみるとなかなか面白いです。

# continuous switch to other window
bind ^N eval 'next' 'command -c cselect'
bind ^P eval 'prev' 'command -c cselect'
bind -c cselect ^N eval 'next' 'command -c cselect'
bind -c cselect ^P eval 'prev' 'command -c cselect'

連続的にウィンドウを切り替える設定です。「Ctrl-A Ctrl-[NP]」でウィンドウを一つ前/後に切り替えたあと、ウィンドウ切替モード(仮称)に移行します。対象とするウィンドウに切り替え終えたら Ctrl-G 等で入力待機状態をキャンセルします。

# list of all windows is displayed in the blank window(-b) for visual window selection.
# override default `w'(windows) mapping.
bind w  windowlist -b
bind ^W windowlist -b -m # sorting by most-recentry-used list.

デフォルトで w に割り当てられている windows は一行で見づらくて役に立たないので、代わりにウィンドウリストの表示を割り当てています。Ctrl-W は「最近使ったウィンドウ順(MRU)」にウィンドウリストを表示します。-b オプションはウィンドウリストを一時ウィンドウに表示するというオプションです。

# move cursor to begining of scrollback buffer(and move to the leftmost column of the window top)
bindkey -m ;b stuff "g/:\015\006\002"

スクロールバッファの先頭を表示しようと試みるコマンドです。今はあまり使いません。くわしくは以前のエントリ スクロールバッファの空白ではない始めの行に移動する方法 を参照。

# refuses yet another hack in rpm packaged screenrc.
# both ] and ^] does write the paste (default unnamed) buffer.
bind ^] paste .

コピペモードの開始 copy が [ と Ctrl-[ であるように、ペーストバッファの貼り付け paste も ] だけでなく Ctrl-] で出来るように割り当てています。これで貼り付けようとしたときに Ctrl を離し忘れていてガッカリすることが無くなります。

# enable background-color-erase setting.
defbce on

# use bright colors for bold text.
attrcolor b '.I'

# the $TERM variable set to `xterm' for various environment.
term xterm

# enable 256 color
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'

# don't resize terminal width when re-attached.
termcapinfo xterm 'is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l'

このへんの端末出力に関わるあたりはコピペです。あまりよく分かっていません。

# changes the windowlist format to suit caption/hardstatus
windowlist title  '%{u .g}Num Flags Title%=[0-9] select the number [movement] j,C-n:Down k,C-p:Up (C-)f:PageDown (C-)b:PageUp'
windowlist string '%{.g}%3n %{.y}%f%09=%{dg} %t %='

ウィンドウリストに表示される内容をカスタマイズしています。1行目ではウィンドウリストのタイトルの色とかヘルプっぽいメッセージを、2行目ではウィンドウリストの書式を定義しています。私の基本設定では色はグリーン(g)ですのでそれに合わせて変えています。色の書式については screen(1) の STRING ESCAPES の後半を参照してください。windowlist で指定する色は captionhardstatus で揃えます。揃えるときは後述する .screenrc.local で上書くようにしています。

caption always '%?%F%{= gW}%:%{= Kk}%?%2n%f%07=%t%='

ようやくきました caption。ここは書式をバラして解説。

%?%F%{= gW}%:%{= Kk}%?%2n%f%07=%t%=
%?%F       %:       %?                -- (1) IF/ELSE フォーカスがあるかないか(%F)を条件にする
    %{= gW}                           -- (2) フォーカスがある場合、以降の前景色をg、背景色をWにする
             %{= Kk}                  -- (3) フォーカスがない場合、以降の前景色をK、背景色をkにする
                      %2n             -- (4) ウィンドウ番号を2桁幅で出力
                         %f           -- (5) ウィンドウのフラグを出力(「(L)」とか「Z」とか「@」とか)
                           %07=       -- (6) 7桁パディング(フラグの出力幅は不定だけど7桁あれば足りるだろう)
                               %t     -- (7) ウィンドウタイトルを出力
                                 %=   -- (8) 残り右全部パディング(右端まで背景色を有効にするため)

こうすると「 1(L) zsh」や「13 vim」という風にウィンドウの番号、フラグ、ウィンドウタイトルが表示されます。フォーカスのあるなしで caption の色を変えていますので、現在どの領域にフォーカスがあるのか把握しやすくなると思います。

hardstatus alwayslastline '%m/%d %02c:%s %{= .g}%H%{-} %L=%-w%45L>%{=u g.}%n %t%{-}%+w %-17<%=%{= .y}(%l)'

つぎは hardstatus。これも書式をバラして解説。

%m/%d %02c:%s %{= .g}%H%{-} %L=%-w%45L>%{=u g.}%n %t%{-}%+w %-17<%=%{= .y}(%l)
%m/%d %02c:%s                                                                  -- (1)
              %{= .g}%H%{-}                                                    -- (2)
                            %L=                                                -- (3)
                               %-w                                             -- (4)
                                  %45L>                                        -- (5)
                                       %{=u g.}%n %d%{-}                       -- (6)
                                                        %+w                    -- (7)
                                                            %-17<              -- (8)
                                                                 %=            -- (9)
                                                                   %{= .y}(%l) -- (10)
  1. タイムスタンプ(月/日 時:分:秒)
  2. 背景色gでホスト名を表示(して背景色を元に戻す)
  3. ウィンドウ一覧のタブ表示の開始位置
  4. 表示中のウィンドウより小さい番号のウィンドウ一覧
  5. ウィンドウ一覧をスクロールさせる左端を45%で指定(この解説は自信なし)
  6. 前景色gで下線付きでウィンドウ番号とタイトルを出力
  7. 表示中のウィンドウより大きい番号のウィンドウ一覧
  8. 右の余白を半角17文字確保
  9. 残り右全部をパディング(余白を最大限広げるため)
  10. ロードアベレージを背景色yで表示

わたしが hardstatus に求めるものは以下のようなものです。

  • 端末エミュレータは常に全画面で表示する事が多いので時計は必須(crontabを編集するときの時刻確認に便利)
  • いくつかのハブホストで screen を起動することがあるので間違えないようにホスト名が欲しい
  • windowlistselect で選べばよいが、ウィンドウ一覧をタブ風に表示していた方が嬉しい時もある
  • ハブホストごとに色は揃えたい

ロードアベレージはオマケです。主に仕事で使っている screen では SNMP で監視対象の値を取得してそれを表示する perl スクリプトを backtick に指定して %0` などとしていますが、ウィンドウ一覧のところを置き換えている以外は上記と一緒です。hardstatus は screen をどのような用途で使うかによって大きく異なりますが、スクリプトを用意することである程度なんでも表示できるので1行スクリプト職人の腕の見せ所です。

# include hostlocal .screenrc
source '.screenrc.local'

ホスト固有の定義を記述しているファイルを source で読み込んでいます。設定ファイルの最後で読み込むことにより、screen のベースとなる設定は .screenrc に、色調や固有のコマンド定義などは .screenrc.local にと設定ファイルを分けるようにしています。

# copy the screen pastbuffer to the MacOSX pastebord
bindkey -m ' ' eval 'stuff \040' 'writebuf' 'exec sh -c "/usr/bin/pbcopy < screen/screen-exchange"'
bindkey -m Y   eval 'stuff Y' 'writebuf'    'exec sh -c "/usr/bin/pbcopy < screen/screen-exchange"'
bindkey -m W   eval 'stuff W' 'writebuf'    'exec sh -c "/usr/bin/pbcopy < screen/screen-exchange"'

次は .screenrc.local の解説。こちらは .screenrc との差分を定義しているだけなのでシンプルです。以下は家で使ってる MacBook の設定なので他の方にはあまり役に立たないかもしれません。これは以前かいた記事 screenのペーストバッファを自動でOSXのクリップボードに送る方法 そのままなのでそちらを参照。bufferfile で指定したファイル名に揃えておく必要があります。

# alias for remote login
# override default `^V'(digraph) mapping
bind ^V eval 'command -c rlogin'           'echo "login to:                [0]                  [1]xeus              [2]vmm.vm            [3]                  [4]intra             [5]                  [6]                  [7]                  [8]                  [9]qnap         "'
bind -c rlogin 1 eval 'screen -t xeus  10 ssh xeus'
bind -c rlogin 2 eval 'screen -t vmm   20 ssh vmm'
bind -c rlogin 4 eval 'screen -t intra 40 ssh intra' eval 'encoding eucjp'
bind -c rlogin 9 eval 'screen -t qnap  90 ssh qnap'

これは screen をリモートホストへ ssh するためのランチャのように使う設定です。デフォルトで Ctrl-V に割り当てられている digraph を私は使うことがないので、そこにリモートログインモード(仮称)を割り当て、次に数字を入力することで定義してあるホストへ ssh します。ホスト名は気にしないでください。

仕事で使っている設定では Web サーバ群、DB サーバ群、開発サーバ群、などともう一つサブカテゴリを作って入れ子にしています。この ssh ランチャ風設定と zombie を組み合わせるとリモートホストへのログインする時のタイプ数がかなり減ります。

ダラダラと解説してきましたが、以上が現在私の使用している GNU Screen の設定です。設定ファイルは 前回(.screenrcを晒してみる) とそれほど変わらず、あまり使ってない定義やよくわからないコピペものもありますが、日々 screen を使っていく中でいろいろと調整してきました。いまのところこの設定で満足していますので冒頭のタイトルに対する回答は「大丈夫だ、問題ない。」ですが、「一番いい奴」を求めて日々人様の設定を参考にしています。

captionhardstatus の解説のしかたは @shyouhei さんの 俺の .screenrc が火を吹くぜ を参考にさせていただきました。入れ子方式やその他解説をみて、ここまで screen の設定をカスタマイズしている人がいたのかと年初にこの記事を見たときは衝撃を受けました。これは全 screen 使い必見モノのエントリです。

実際のところこの設定は git 版 screen 用の設定ファイルから source して使っています。git 版の設定ファイルの解説については新機能の紹介とともにそのうちやります。

それではよい GNU Screen ライフを!

0 件のコメント:

コメントを投稿