screen への誘い

Ippei Kishida

Last-modified:2016/04/26 23:38:02.

『UNIX今日の技』の screen に関する項目を纏めたものです。

多くの人には「screen?何それ美味しいの?」ってな感じでしょう。 でも、少し覚えれば結構美味しいです。 私も極める程には使えてないので紹介程度しか出来ませんが。

screen はターミナル上で動くアプリケーションで、ターミナルとして動きます。 どういうことかというと、ログインしたターミナルで「screen」を実行してやると、kterm や putty といった比較的低機能なターミナルを、高機能な「screen ターミナル」として使えるということです。

……分かり難いですか? まあ追々分かると思います。

screen には他のターミナルにない優れた機能があります。 ……ということで幾つか機能を紹介していくつもりなんですが、デフォルトの状態では使い難いので最初に私の設定ファイル(~/.screenrc)を公開しておきます。 とはいうてもネットから拾って来たものをあまり理解せず使ってるだけですが。

## screen        last modified : 2004-07-26

escape ^T^T             # prefixキーをC-tに変更する
vbell off               # visible bell を使用するか
# bind w windowlist -b  # window list の表示方法を変更
deflogin off    # 新しいwindowを開く度に/etc/utmpにentryを追加するか
bell "Bell in window %." # 隠れているwindowでのbellを通知
activity "Activity in window %." # 隠れているwindowの状態変化を通知
autodetach on   # 回線が切れた場合に自動的にデタッチするか
# detach on hangup
startup_message off     # スタートアップページを表示するか
termcapinfo  xterm|kterm|kterm-color 'hs:ts=\E]2;:fs=\007:ds=\E]0;screen\007'
                        # タイトルバーをステータス表示に使う
terminfo xterm|kterm|kterm-color XT # for mice
shell -$SHELL # make the shell in every window a login shell
defscrollback 1000

hardstatus string " %m/%d %D %c [%n:%Lw] %H:%h" # status表示のformat
## m:month, d:day, D:weekday, c:current time in 24h,
## n:window number, w:all window numbers, H:hostname,
## h:hardstatus of the window, l:current load of the system
# defhstatus "^En:^Et"
# defhstatus "screen: ^E (^Et)"

以下の説明ではこの設定ファイルを前提に話を進めて行きます。

1 screen の起動(screen)

まず screen を起動しなくては始まりません。 ログインしたターミナルで「screen」と打てば screen が起動します。 screen から抜けるには普通にログアウトするように 「exit」 や [C-d] で抜けられます。

2 ウィンドウ管理

物理的には一つのターミナルだけれども、あたかも複数のターミナルがそこにあるかのように切り替えて使用することができます。

要は、「幾つも kterm や putty を起動して一々ログインするのは面倒。一個接続したらその中でウィンドウを切り変えて使うことができる」ということです。

2.1 新しいウィンドウを開始する([c-t] c)

「[C-t] c」で新しいウィンドウを開始できます。 幾つでも作れます。 不要になったウィンドウは 「exit」 や [C-d] で消せます。

2.2 別のウィンドウに移動する([C-t] [SPACE] など)

「[C-t] [SPACE]」 次のウィンドウに移動 「[C-t] [BS]」 1つ前のウィンドウに移動 *「[C-t] 0」 0 番目のウィンドウに移動

「[C-t] [SPACE]」 で動き回って、ウィンドウが足りなければ「[C-t] c」で作って、余れば「[C-d]」で消す、というのが私がよくやる使い方です。

2.3 プロンプトにウィンドウ番号を表示する

シェルのプロンプト変数に「\({WINDOW:+"[\)WINDOW]“}」というオマジナイを入れておくとウィンドウ番号を表示できます。 例えば、現在私が使用しているプロンプトは以下のようになってます。 PS1=\('%{\e]2; %m:%~ \a'\)‘]1;%%: %~%}’\('\n%{\e[\){PSCOLOR}m%}%n@%m \({WINDOW:+"[\)WINDOW]”}%#%{% (← screen でのプロンプト)

ともかく、このように現在のターミナルが screen なのか違うのか、screen ならばどのウィンドウにいるのかが一目瞭然になります。

3 レジューム(screen -r)

リモートログインでジョブを走らせている時に通信が断絶すると、そのジョブも巻き添えを喰って死んでしまいます。 そういう時 screen を使っていると、リモートホストで走っている screen が、次回「screen -r」でレジュームされるまでそのジョブを(正確にはシェルを)ガッチリ守ってくれます。

4 デタッチ([C-t] d)

意図的に通信を切断したい、だけどリモートホストのジョブは残したいという場合には「[C-t] d」でデタッチします。 デタッチしたセッションはレジューム(「screen -r」)で復帰できます。

5 マルチアタッチ(screen -x)

「screen -x」で起動すれば、既に開かれているセッションにアタッチすることができる、すなわち1つのセッションに複数のターミナルからアクセスできます。 ……これが結構味わい深い。

私はよく、ローカルホスト自身で screen セッションを開いて、横の Windows マシンから接続したターミナルで screen のマルチアタッチをします。 こうしておけば、両方のホストから同じウィンドウにアクセスできます。

もっと具体的に言うと、そのセッションで mp3 をランダム再生してます。 その再生スクリプトの操作を UNIX ホストからでも Windows ホストからでも行える、ということです。 ……だって、Windows 使ってる時に画面切り替えするの面倒やし。

あと、ついつい Windows 側のターミナルでメールを書きかけてしまった場合、画面を切り替えて UNIX ホスト側のターミナルでキチンと入力するというのもよくやります。 (Windows のターミナル上で vim を起動してそこで日本語入力するというのは結構苦痛なので)。

……かなり特殊な使い方のような気もします。 マルチアタッチのちゃんとした使い方って、どんなんなんでしょうか?

6 セッションとウィンドウ

今まで何も説明せずにセッションという言葉を使って来ましたが、screen はセッションとウィンドウという単位で状態を管理します。

ウィンドウというのは、screen 上で「[C-t] c」などで増やせる、シェルが動いてるアレです (一個一個の端末と呼ぶべきでしょうか)。 そして複数のウィンドウを束ねているのがセッションです。

同一 PC 上でユーザは複数のセッションを持つことができます。

7 存在するセッションを一覧表示(screen -ls)

ippei@odin % screen -ls
There are screens on:
        17012.ttypc.odin        (Attached)
        64693.ttyp1.odin        (Detached)
        64721.ttyp1.odin        (Detached)
3 Sockets in /tmp/screens/S-ippei.

3つの screen セッションが存在し、1つはアタッチされていて 2つはデタッチされていることが分かります。 ここでデタッチされている一方を指定してアタッチ(レジューム)したい場合は、 % screen -r 64693.ttyp1.odin % screen -r 64693 (「.」以降は省略しても OK) のように指定します。

8 コピーモード([C-t] ESC)

私はあまり使ってないのでザッと概説だけ。 流れていった標準出力のログを見たり、バッファに入れてどこかにコピーしたりというのに使えるようです。

基本的には「[C-t] [ESC]」でコピーモードに入って hjkl でカーソル移動して、[ESC] で抜けるらしいです。

9 ヘルプの表示([C-t] ?)

「[C-t] ?」でヘルプが出るので使いながらキーバインドを調べることも出来ます。

10 prefix キーの変更

さて、今まで screen 上で screen コマンドを呼出すのには [C-t] を使うと説明して来ましたが、これはこのように設定したから [C-t] になっているだけで、デフォルトでは [C-a] になっています。 でもシェルの操作に emacs キーバインド使ってる人にとっては行頭に飛ぶのに使ってるので [C-a] なんかに当てられてると使い難くてしゃあないです。 これを別のキーに割当てたい場合は ~/.screenrc の以下の部分を適当に変更すれば行ける筈です。

escape ^T^T             # prefixキーをC-tに変更する

11 screen: screen -xR

screen セッションを複数開くとどのセッションでどの作業をやっているかが分かり難くなるため、私はいつも1つのセッションだけ開き、それにマルチアタッチして操作しています。 この辺は『マルチアタッチ(screen -x)』の項で紹介しました。 しかし「screen -x」は既に開いているセッションが存在しなければ使えず、「There is no screen to be attached.」と文句を言われてしまいます。

かといって毎回「screen -ls」で開いているセッションが存在するかを確認するのも面倒です。 そこで screen を「screen -xR」として起動してみましょう。 こうすると screen は既に開いているセッションが存在すればそれにマルチアタッチする形で、存在しなければ新しいセッションを作ります。 ここで注意すべきは、オプションの順序が重要になってくることです。 「screen -Rx」では毎回新しいセッションを開いてしまい、望むべく動作しません。

どうしてそうなるか、もうちょっと深く見ていきます。 screen のオプション解析では、-x、-R オプションは指示された順番通りに条件判定を行い、そのオプションで実行できるならそのように実行、そうでなければ単純に無視するようです。

オプション -R は -r と同じくデタッチされたセッションをレジュームするオプションです。 レジュームすべきセッションがない場合、-r オプションではそのまま終了しますが、 -R オプションでは新しくセッションを作ります。

この結果、「screen -xR」では以下のように条件判断していることになります。 0. 開いているセッションがあればそれにマルチアタッチ 0. 開いているセッションはないがデタッチされたセッションがあればそれにレジューム 0. 全くセッションがなければ新しくセッションを作成

ちなみに、私は「alias scr=“screen -xR”」として ~/.zshrc に仕込んでいます。