2018-09-04

GNU screen コマンド勉強録

いまさらですが今後必要になりそうなので screen を覚えることにしました。

この記事は入門的な内容&必要以上に長いので既に理解している人はリファレンスを見たほうがいいです。

screen とは

一つのターミナルで複数の画面を管理することができるGNU製のソフトウェアです。

最近のターミナルソフトウェアはタブや画面分割機能が存在するためローカルでscreenを使用するメリットはそこまで大きくありません。

しかしサーバ用途としては有用です。その理由は screen はサーバのプロセスとして居座るところにあります。

普通リモート接続が切断されるとその接続プロセスを親とするシェルも終了されるため、実行中の処理は中断しコンソールの内容も失われます。 screenの下で実行されたプロセスはscreenプロセスさえ生きていれば処理やコンソールのログも残るというわけです。 そのためリモートでのリリース作業などはscreenコマンドを介して行うと安全に実行できるのですね。

info
  • 後発のソフトウェアとして tmux があります。基本的にできることは同じですが、以下の点で開発用途としてはtmuxのほうが優秀です。
    • プラグインの多さ
    • カスタマイズ性
    • 動作の軽快さ
  • vimmer の方は tmux なんて当たり前の話かもしれませんが、そうでない場合も非常に有用なので利用をオススメです。
  • screen は大抵のサーバにインストールされているのでリモート接続して作業するようなケースで有用です。

Session

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

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

Attach

アタッチすることでセッションは使用可能な状態となります。

セッション生成直後は自動でアタッチされた状態です。

既に存在するセッションをアタッチするには-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プロセスが残ってしまうことがあります。 以下のようにデタッチを行いましょう。

Detach

使用中のセッションから抜けるためにはデタッチを行う必要があります。

デタッチしてもセッションで実行中の処理は消えません。

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

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

List

セッションの一覧を確認するためには-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.

Region

screenでは画面を上下(左右)に分割することができます。

左右の分割は比較的新しい機能らしく、新しいバージョンであれば使用可能です。 今回は縦分割が有効なバージョンを使用します。

(Screenversion 4.01.00devel (GNU) 2-May-06)

この分割された部分をリージョン(領域)と呼びます。

セッションはこのリージョンを1つ以上もちます。

Window

ウィンドウはシェルを持ち、ユーザはシェルを操作することになります。

セッションによって1つ以上のウィンドウが管理されます。

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

つまり見えていても操作できないリージョンということもありえます。

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

文章ではわかりづらいので次のセクションから 操作表示 を簡易的に再現してみます。

操作

セッションアタッチ後はscreenの独自コマンドが利用できます。

コマンドの構文はprefix+特定キーです(prefixを押した後に特定キー)。

prefixはデフォルトで Ctrl + a が設定されています。

? Help

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, d Detach

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

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

^Z, z Suspend

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

[1]+ Terminated screen
$ _

再開するにはシェルコマンド fg を使いましょう。

サスペンド中のセッションはデタッチ状態となるため -r で再開することも可能ではあります。

\ Quit

さて、重要なscreenプロセスの終わらせ方です。

本当に終了していいか聞かれるので、よければ「y」を押します。

$ _
Really quit and kill all your windows [y/n]

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

info
  • Mac で動かなかったので、検証できず (9/4)

S Split

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

$ _
0 bash

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

| Vertical split

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

$ _
0 bash

Tab Move

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

$
0 bash
_

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

$
0 bash
_

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

$ _
0 bash

元の場所に戻りました。

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

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

X Remove

右上のリージョンを削除してみましょう。

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

$ _
0 bash

Q Close the others

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

$ _

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

^C, c Create a new screen

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

$
0 bash
$ _
1 bash

もう一度やってみます。

$
0 bash
$ _
2 bash

1 bash2 bash に変わりました。

このようにウィンドウには番号が割り当てられ、未使用の数値が小さい順に使用されます。

この場合では下のリージョンに3つ目に作成されたウィンドウに「2」が割り当てられ、 現在は 2 bash が表にいるってことですね。

「1」は隠れているだけで消えてしまったわけではありません。

^W, w Windows

info
  • OS の Windows とは無関係です

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

$ _
0 bash
$
0$ bash 1-$ bash 2*$ bash

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

info
  • 数値と「$」の間にある記号
    • * は直近で表示(または作成)されたウィンドウ、必ずしもカレントウィンドウとは限りません
    • - は直近で非表示となった ウィンドウ を表しています。

k (K) Kill

info
  • Mac では 大文字の K が動かなかったので (K) としてあります。

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

$ _Really kill this window [y/n]
0 bash
$
2 bash

続けて「y」を入力するとウィンドウが削除されます。

また、ウィンドウはシェルと結びついているため、シェルコマンドの exit でも削除することができます。

$ _
1 bash
$
2 bash

' Select

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

Num NameFlags
 
  1 bash$
  2 bash$
$
2 bash

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

$ _
2 bash
$
2 bash

どちらのリージョンにも 2 bash が表示されるようになりました。

せっかく上下のリージョンでウィンドウが同じになったのでなにか入力してみましょう。

$ echo test
test
$ _
2 bash
$ echo test
test
$
2 bash

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

0 ~ 9 Select

ウィンドウに振り当てられている番号を指定して切り替えます。

キーは「0〜9」までの数値と「-(ハイフン)」です。

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

$ echo test
test
$ _
2 bash
$ echo test
test
$
1-$ bash 2*$ bash

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

次に「1」を入力してみます。

$ _
1 bash
$ echo test
test
$
2 bash

prefixの後に入力できる文字は一文字に限られているためこの方法により切り替えられるのは先頭10個までのウィンドウに限られます。

それ以上の番号が割り当てられたウィンドウに切り替えるためには前述した 選択方式のウィンドウ切り替え " か入力式のウィンドウ切り替え ' を利用しましょう。

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

n, ^N, space key Next

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

$ echo test
test
$ _
2 bash
$ echo test
test
$
2 bash

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

現在1と2しかないので2に移動しました。 すこしわかりにくいですね。反省はしていない。

p, ^P, ^H, ^? Prev

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

$ _
1 bash
$ echo test
test
$
2 bash

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

^[, [ Copy

ウィンドウの文字列をコピーするのに使用します。

実行するとフリーカーソルとなり、スペースで開始・終了位置を決定します。

echoの後ろの「test」をコピーしてみます。

「test」の先頭の「t」まで方向キーで移動してスペースを押します。

選択モードになったら、方向キーで終端文字まで移動しましょう。

$
1 bash
$ echo test
test
$ _
2 bash

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

$
1 bash
$ echo test
test
$ _
Copied 4 characters into buffer

^], ] Paste

上でコピーしたものを貼り付けてみましょう。

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

$ test_
1 bash
$ echo test
test
$
2 bash

> Write buffer

バッファ文字列をファイルに書き出します。

デフォルトで対象ファイルは /tmp/screen-exchange となっているようです。

$ test_
1 bash
$ echo test
test
$
Copybuffer written to “/tmp/screen-exchange”.
info
  • 空文字を書きこむとファイルの内容が消えますが, = でファイル自体を削除できます。

< Read buffer

ファイルからバッファに対して文字列を読み込みます。

デフォルトで対象ファイルは /tmp/screen-exchange となっているようです。

$ test_
1 bash
$ echo test
test
$
Slurped 4 characters into buffer.
info
  • ファイルがない状態でバッファを読み込もうとすると no /tmp/screen-exchange -- no slurp: No such file or directory となります