GNU screen コマンド勉強録

いまさらですが今後必要になりそうなのでscreenを覚えることにしました。
この記事は入門的な内容&必要以上に長いので既に理解している人はリファレンスを見たほうがいいです。

screenとは

一つのターミナルで複数の画面を管理することができるGNU製のソフトウェアです。
最近のターミナルソフトウェアはタブや画面分割機能が存在するためローカルでscreenを使用するメリットはそこまで大きくないでしょう。

もうひとつの特徴として、screen上の操作は起動元のプロセスが落ちても消えません。
そのため、リモート操作する際に中断されたら困る処理(手動バッチなど)はscreenコマンドを介して行うと安全に実行できます。

セッション

screenを実行した時点でセッション(プロセス)が生成されます。-Sオプションを使用するとセッション名を指定できます。

セッションは次の2つの状態を持ちます。

アタッチ(Attached)

アタッチすることでセッションは使用可能な状態となります。
セッション生成直後は自動でアタッチされた状態です。
既に存在するセッションをアタッチするには-rオプションでセッションのPIDかセッション名を指定します。

このとき既にアタッチされているセッションをアタッチすることはできません。

user@main:~$ screen -r 28217
There is a screen on:
1111.pts-32.main (2015年01月01日 01時01分01秒)   (Attached)
There is no screen to be resumed matching 1111.

何らかの原因によりscreen呼び出し元のプロセス(シェル)が終了してしまった場合、上記のようにアタッチ状態のscreenプロセスが残ってしまうことがあります。
以下のようにデタッチを行いましょう。

デタッチ(Detached)

使用中のセッションから抜けるためにはデタッチを行う必要があります。
デタッチしてもセッションで実行中の処理は消えません。

-dオプションを使うとPIDかセッション名に該当するセッションを強制的にデタッチすることができます。

user@main:~$ screen -d 1111
[1111.pts-32.main detached.]

一覧

セッションの一覧を確認するためには-lsか-listオプションを使います。

$ screen -ls
There are screens on:
	2222.pts-32.main (2015年02月02日 02時02分02秒)	(Detached)
	1111.testscreen  (2015年01月01日 01時01分01秒)	(Attached)
2 Sockets in /var/run/screen/S-user.

リージョン

screenでは画面を上下(左右)に分割することができます。
左右の分割は比較的新しい機能らしく、新しいバージョンであれば使用可能です。今回は縦分割が有効なバージョンを使用します(Screen version 4.01.00devel (GNU) 2-May-06)
この分割された部分をリージョン(領域)と呼びます。
セッションはこのリージョンを1つ以上もちます。

ウィンドウ

ウィンドウはシェルを持ち、ユーザはシェルを操作することになります。
セッションによって1つ以上のウィンドウが管理されます。

そしてリージョンに対しても複数のウィンドウを割り当てることができます。この割り当ては必須ではありません。
つまり見えていても操作できないリージョンということもありえます。

セッションに属するすべてのウィンドウを削除するとセッションも自動的に消えます。

文章ではわかりづらいので「操作」と「表示」を簡易的に再現してみます。

操作

セッションアタッチ後はscreenの独自コマンドが利用できます。
コマンドの構文はprefix+特定キーです(prefixを押した後に特定キー)。prefixはデフォルトで「Ctrl + a」が設定されています。

[ ? ] ヘルプを表示する

Screen key bindings, page 1 of 1.

Command key:  ^A   Literal ^A:  a

break       ^B b    hardcopy    h       monitor     M            remove      X       version     v
clear       C       help        ?       next        ^@ ^N sp n   removebuf   =       width       W
colon       :       history     { }     number      N            reset       Z       windows     ^W w
copy        ^[ [    info        i       only        Q            screen      ^C c    wrap        ^R r
digraph     ^V      lastmsg     ^M m    pow_break   B            silence     _       xoff        ^S s
detach      ^D d    kill        K k     other       ^A           select      '       writebuf    >
displays    *       license     ,       pow_detach  D            split       S       xon         ^Q q
dumptermcap .       lockscreen  ^X x    prev        ^H ^P p ^?   suspend     ^Z z
fit         F       log         H       quit        \            time        ^T t
flow        ^F f    login       L       readbuf     <            title       A
focus       ^I      meta        a       redisplay   ^L l         vbell       ^G

^]   paste .
"    windowlist -b
-    select -
0    select 0
1    select 1
2    select 2
3    select 3
4    select 4
5    select 5
6    select 6
7    select 7
8    select 8
9    select 9
I    login on
O    login off
]    paste .
|    split -v
:kB: focus prev

とりあえずリンクをつけてみました。(全部は無理ですごめんなさい)

[ d ] セッションをデタッチする

現在アタッチ中のセッションをデタッチします。

[detached from 2222.pts-32.main]
$ _

[ z ] セッションをサスペンドする

現在アタッチ中のセッションを停止(サスペンド)します。

[1]+ Terminated screen
$ _

再開するにはシェルコマンドを「fg」を使いましょう。
サスペンド中のセッションはデタッチ状態となるため-rで再開することも可能ではあります。

[ \ ] セッションを終了する

さて、重要なscreenプロセスの終わらせ方です。
本当に終了していいか聞かれるので、よければ「y」を押します。

$ _

当たり前ですが再開はできません。

[ S ] リージョンを横分割する

実行すると以下のように上下に分割されます。

$ _

※カレントリージョンが赤です

[ | ] リージョンを縦分割する

実行すると以下のように左右に分割されます。

$ _

[ Tab ] リージョンを移動する

キーは「Tab」です。一度実行してみます。

$
_

右に移動しました。
もう一度実行すると

$
_

下に移動しました。
もう一度(ry

$ _

元の場所に戻りました。

リージョンの移動規則は以下のようになっているようです。

  1. 現在いるリージョンから派生したリージョン(以下子リージョンという)の直近へ移動
  2. 1がなければ派生元リージョンを辿っていき、別の子リージョンがあればそれに移動(複数ある場合は新しいもの)
  3. 2がなければ先頭リージョンへ移動

[ X ] リージョンを削除する

右上のリージョンを削除してみましょう。カレントリージョンが削除されるので右上にカレントリージョンを移しておく必要があります。

$ _

[ Q ] リージョンをまとめて削除する(分割を解除する)

カレントのリージョンだけを残して他のリージョンが削除されます。

$ _

ウィンドウは見えなくなりますが削除されるわけではありません。

[ c ] ウィンドウを作成する

開いてるリージョンにウィンドウを作成してみましょう。

$
$ _

もう一度やってみます。

$
$ _

「1 bash」が「2 bash」に変わりました。
このようにウィンドウには番号が割り当てられ、未使用の数値が小さい順に使用されます。

この場合では下のリージョンに3つ目に作成されたウィンドウに「2」が割り当てられ、現在は「2 bash」が表にいるってことですね。
「1」は隠れているだけで消えてしまったわけではありません。

[ w ] ウィンドウ一覧を表示する

一旦存在するウィンドウの確認をしてみましょう。

$ _
$

下リージョンのメッセージ部分に表示されましたね。
数値部分が先頭のウィンドウ番号にあたります。

数値と「$」の間にある記号

「*」は直近で表示(または作成)されたウィンドウ、必ずしもカレントウィンドウとは限りません
「-」は直近で非表示となったウィンドウ
を表しています。

[ K ] ウィンドウを削除する

上のリージョンに表示されているウィンドウを削除してみましょう。

$ _Really kill this window [y/n]
$

続けて「y」を入力するとウィンドウが削除されます。
また、ウィンドウはシェルと結びついているため、シェルコマンドの「exit」でも削除することができます。

$ _
$

[ ” ] ウィンドウを選択して切り替える

実行するとウィンドウの一覧が現れ、選択すると切り替わります。

Num Name Flags
 
  1 bash $
  2 bash $
$

今回は「2 bash」を選択してみましょう。

$ _
$

どちらのリージョンにも「2 bash」が表示されるようになりました。
せっかく上下のリージョンでウィンドウが同じになったのでなにか入力してみましょう。

$ echo test
test
$ _
$ echo test
test
$

同じウィンドウなので同じものが入出力されますね。

[ 0-9 ] ウィンドウを指定して切り替える

ウィンドウに振り当てられている番号を指定して切り替えます。キーは「0〜9」までの数値と「-(ハイフン)」です。

「0」を入力してみます。

$ echo test
test
$ _
$ echo test
test
$

「0」が割り当てられたウィンドウは存在しないため切り替わらず、下のリージョンにウィンドウの一覧が表示されます。
次に「1」を入力してみます。

$ _
$ echo test
test
$

prefixの後に入力できる文字は一文字に限られているためこの方法により切り替えられるのは先頭10個までのウィンドウに限られます。
11以上の番号が割り当てられたウィンドウに切り替えるためには前述した選択方式のウィンドウ切り替え( ” )か入力式のウィンドウ切り替え( ‘ )を利用しましょう。

「-」を入力するとシェルが割り当てられていないウィンドウに切り替わります。

[ p ] 前のウィンドウに移動する

カレントウィンドウを起点として、ウィンドウ番号が大きい直近のウィンドウに移動します。

$ echo test
test
$ _
$ echo test
test
$

カレントウィンドウが先頭の場合は、最後のウィンドウに移動します。現在1と2しかないので2に移動しました。
すこしわかりにくいですね。反省はしていない。

[ n ] 次のウィンドウに移動する

カレントウィンドウを起点として、ウィンドウ番号が小さい直近のウィンドウに移動します。

$ _
$ echo test
test
$

カレントウィンドウが最後の場合は、先頭のウィンドウに移動します。

[ [ ] バッファにコピーする

ウィンドウの文字列をコピーするのに使用します。
実行するとフリーカーソルとなり、スペースで開始・終了位置を決定します。
echoの後ろの「test」をコピーしてみます。
「test」の先頭の「t」まで方向キーで移動してスペースを押します。
選択モードになったら、方向キーで終端文字まで移動しましょう。

$
$ echo test
test
$ _

反転している文字がコピー対象です。再度スペースを押すとバッファにコピーされます。

$
$ echo test
test
$ _

[ ] ] バッファをペーストする

上でコピーしたものを貼り付けてみましょう。
ウィンドウをまたいで貼り付けることができるので上のリージョンに貼り付けてみましょう。

$ test_
$ echo test
test
$

[ > ] バッファをファイルに書き出す

バッファ文字列をファイルに書き出します。デフォルトで対象ファイルは「/tmp/screen-exchange」となっているようです。

$ test_
$ echo test
test
$

[ < ] ファイルからバッファに読み込む

ファイルからバッファに対して文字列を読み込みます。デフォルトで対象ファイルは「/tmp/screen-exchange」となっているようです。

$ test_
$ echo test
test
$

参考リンク: http://www.limy.org/program/screen.html