screenコマンド入門

## いきさつ
Linuxで使われるscreenコマンドについて学ぶ機会があったので、まとめていきます。


## 概要
screen (GNU Screen) とは、1つの画面で複数のプロセス、というより端末環境を動作させるソフトウェアです。Man page にはちゃんとした説明が書いてますが、物は試しで動きを見た方がわかりやすいです。

## 実践
### まずは動かす
まずはシンプルに screen と打ってみます。
```console
$ screen
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/99efd1c0-e768-165b-4948-c5190cc7472d.png)
Screenのコピーライトのようなものが表示されます。

ここから Enter キーを押すとシェルが開きます。見た目はログイン直後の状態と同じです。ですが確かに screen の中にいます。
後に行う手順のために、echo とか date とか適当なコマンドを打っておきましょう。
```console
(on screen shell)
$ echo hello from screen
hello from screen
```

screen に対するコマンドは Ctrl-a キーを押したあと、対応するキーを押すことで実行できます。試しに Ctrl-a キーを押し、その後 ? キーを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/cb7acdf8-8f95-9691-a00a-dffef94d5633.png)

screen のコマンド一覧が出力されます。今実行した `Ctrl-a ?` は、この画面を表示する help コマンドというものになります。Enter キーを押すと元の画面に戻ります。

それでは、 screen から出てみましょう。これを detach と呼びます。Ctrl-a キー を押し、その後 D キーを押します。
```console
(parent shell)
$ screen
[detached from 12420.pts-0.ubuntu-xenial]
$ 
```

screen コマンドを打ったシェルに戻ってきました。screen 上のシェルはどうなっているかというと、依然として動いています。
`screen -ls`を実行すると、screenで何が動いているかを見れます。
```console
(parent shell)
$ screen -ls
There is a screen on:
        12420.pts-0.ubuntu-xenial       (10/23/2023 07:25:48 PM)        (Detached)
1 Socket in /var/run/screen/S-vagrant.
```
さて、screen の特徴はもう一つあり、このようにして一度開いたセッションを維持できるという点です。
端末からログアウトしても、作業状態を保存したままにしておけるのです。例えば長時間走行するプログラムを `nohup` を付けずに実行したままログアウトしても、screenの中で動いたままになってくれます。
上記の例でも再度ログインしてから `screen -ls` を実行すれば、同様の出力が得られるはずです。

では、 screen セッション上のシェルに復帰しましょう。 `screen -r` を実行します。
(detach の反対で attach と呼びます)
```console
(parent shell)
$ screen -r
```
```console
(on screen shell)
$ echo hello from screen
hello from screen
$
```
正しく screen の上で打ったコマンドの結果が出ていますね。最後に、シェルを終わらせましょう。

```console
(on screen shell)
$ exit
```
```console
(parent shell)
[screen is terminating]
$ screen -ls
No Sockets found in /var/run/screen/S-vagrant.
```
`-ls` で見ても何も残っていないことが確認できます。

簡単な使い方が分かったところで、実用例を見ていきます。

### 実例: シェルとテキストエディタ
エディタを開いて編集をしつつ、並行してシェルを立ち上げるという環境を実現してみます。
まずは screen でシェルを開きましょう。
```console
(parent shell)
$ screen
```
テキストエディタでプログラムを書くとしましょう。ここでは vi を使っています。
```console
(on screen shell)
$ vi
```
今回は[Node.jsのサンプルコード](https://nodejs.org/en/docs/guides/getting-started-guide)を動かすことにします。サンプルコードを適当なファイルに保存しましょう。引き続き編集したいのでエディタは閉じずにおいておきますが、一旦コードを動かしてみたいです。
そこで、screen上でもう一つの画面を開くことにします。

まず、 `Ctrl-a |` を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/b8737871-cdc0-98da-95d3-d3b61b334430.png)
先輩、画面が縦に割れました！その通り、screen 上では画面分割を行うことができます。`Ctrl-a |` を実行することで垂直に分割できます。画面下部のバーには画面の番号とコマンド名が記載されています。 ちなみに、水平に分割するには `Ctrl-a S` を実行します。
<details><summary>TL;DR 厳密な定義の話</summary>
分割された領域は<strong>リージョン</strong>と呼ばれます。一方で、screen上で動くシェルなどのプログラムのことを<strong>ウィンドウ</strong>と呼びます。1つのリージョンの中では表示するウィンドウを切り替えることができます。
</details>

今は左画面にカーソルがある状態です。右に映るため、`Ctrl-a <Tab>` を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/50c60917-d253-686c-7a1d-15492398a199.png)
カーソルが移動しました。下にウィンドウ名が出ていますが、ここには何もありません。
新しいシェルを立ち上げましょう。 `Ctrl-a c` を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/a800ce0a-c47a-30a2-1c96-0a5b2f0b5cdf.png)

右画面でシェルが立ち上がりました。パチパチ。それではエディタで保存したであろう `node app.js` を実行してサーバを立ち上げましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/912cc246-f137-4784-a000-ffea2f7b8a15.png)

サーバが起動しました。折角なので `curl` で動作確認を…おっと。右画面ではサーバを動かしていて `curl` を叩けないじゃありませんか。
また別のシェルを立ち上げることにしましょう。先程と同じように `Ctrl-a c` を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/ee44e1e6-0c2a-15d4-a6c2-0827461d471c.png)

3つ目のconsoleが起動しました。今度こそ `curl` の出番です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/88e9c588-f145-dbcc-2d25-096edf8cc9ef.png)

これで、サーバへのHTTPアクセスまでを screen 上で完結させることができました。
あれ？サーバを動かしてる画面はどこへ行ったのでしょう。直近の画面を開くには `Ctrl-a Ctrl-a` を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/69773d80-110c-4028-5678-2e903d88361f.png)

よかった、まだ動いていましたね。
screen 上で並行して動かしている画面はウィンドウと呼ばれ、番号が振られています。

`Ctrl-a "` を実行するとウィンドウの一覧を表示できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/d1e01d34-386d-e39c-7b3d-75e426419601.png)

`Ctrl-a 番号` を実行することで、該当する番号のウィンドウが開かれます。
以下は左側に2番(curlを叩くために開いたウィンドウ)を開いた図です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/249eed6c-bb56-130f-2bfc-3a2451d277d2.png)

例えばサーバアクセスの度にログを出すように改変すれば、横に並べながら動作確認できるわけですね。

最後にお片付けをしておきましょう。 `Ctrl-a \` はすべてを綺麗さっぱり消し去るコマンドです。実行すると、
```
Really quit and kill all your windows [y/n]
```
というメッセージが画面下部に出ます。Y を押すと終了します。

### 画面をスクロールさせるには
シェルで作業していくと文字が上に流れていきますよね。
上の方は何書いてたかしら…あれ！？マウスホイールで上に行けない！
画面分割しているときはこうなります。このようなときは、コピーモードに入ります。
`Ctrl-a [` を実行するとコピーモードに入ります。
カーソルが h,j,k,l キーで動くようになり、k キーやPageDownキーを押し続けて古いログまで遡ることができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/a9a6cfc3-9c81-6154-3d36-13dc84e504c3.png)

分かりにくいですが `ll /bin` を実行した後めっちゃ上まで戻ってきた図です。
コピーモードを抜けるには Esc キーを押します。

## tmux と byobu について少し
Wikipediaで調べてると、 GNU Screen は結構古いものみたいです。
同様のソフトウェアが他にもあります。

### tmux
後発の端末多重化ソフトウェアです。
コマンドの打ち方などは異なるようですが、概ねScreenの互換品として使えるみたいです。BSD系列で普及している雰囲気。

### byobu
Screen や tmux の上に乗っかって、フロントエンドとして動作するソフトウェアです。
使い勝手が向上しているので、新しく導入するならこっちの方がいいかも。
Ubuntu Serverだと標準搭載です。

## 参考情報
* [Linux screenコマンド使い方 - Qiita](https://qiita.com/hnishi/items/3190f2901f88e2594a5f)
* [【図解】screenコマンド入門（迷子向け） - Qiita](https://qiita.com/logiteca7/items/bb5ea4032c141a29e8ce)
* [Man page of SCREEN](https://linuxjm.osdn.jp/html/GNU_screen/man1/screen.1.html) (Linux JM)
* [第12回 ショートカットとByobuを駆使して、UbuntuのCLI操作を効率化しよう](https://pc.watch.impress.co.jp/docs/column/ubuntu/1444004.html)
* [GNU Screen - Wikipedia](https://ja.wikipedia.org/wiki/GNU_Screen)