みんなにもっとCtrl-z使ってもらって、実行中のjobをサスペンドしてCLIがちょっと楽になって欲しい (bash、Zsh)

皆さんこんにちは、かみけんです。
(最近、アカウント名をkmszkからkamyknに変えました。)

# この記事で紹介すること
bashやzshなら実はscreenやtmuxを使わなくてもVimやMySQL CLIなどを一つのウインドウで複数起動できるので、作業が少し楽になるかもという内容です！
これ教えると結構ヘェ〜ってなってる人(年上のプログラマにも意外と…)が多かったので記事にしてみました。

# jobとforegroundとbackground
VimやMySQLなどの開いている状態(実行している状態)のjobはCtrl-zでbackgroundに回すことができます。
backgroundにjobは複数保持することができ、```fg``` (foreground)コマンドによって任意のタイミングで呼び出す(再開する)ことができます。

## fgとjobs
今回登場するコマンドは```fg```と```jobs```になります。(あと、バックグラウンドに回す際のCtrl-zも使います。)

VimやMySQLなどの開いている状態(実行している状態)のjobをCtrl-zでbackgroundに回し、そして必要になったときに```fg```コマンド(foreground)で呼び出しています。

↓↓ (今回紹介する範囲の) jobのサイクルのイメージ

```
[foreground] ─── 入力:Ctrl-z ───> [background]
     ^                                 │
     └──────────── 入力:fg ────────────┘
```



## 実演
おもむろにVimを立ち上げたあとにCtrl-zを押してみましょう。

![ctrlz1.gif](https://qiita-image-store.s3.amazonaws.com/0/73446/a5523824-f83e-5d13-f67b-8f21b183ba0f.gif)

Vimが消えました。

Vimはどこに行ったのでしょう。消えたVimを探すべく、今度は ```jobs``` と打ち込んでみます。

```
❯ jobs
[1]  + suspended  vim ~/.vimrc
```

いました。なにやらVimがsuspended状態であることがわかったので、次に ```fg``` と打ち込んでみます。(または単に ```%1``` でもいいでしょう。)

![ctrlz2.gif](https://qiita-image-store.s3.amazonaws.com/0/73446/56059d7c-ebba-79e3-9e84-ee50dcd85aeb.gif)

無事に先程のvimを開くことができました。
単にfgとすると最後に起動状態にあったjobsに戻ることが出来ます。

次に複数のjobを立ち上げてみます。

またCtrl-zでもどって、今度は```mysql```コマンドを叩いてみます。
再度Ctrl-zでログイン中のmysqlをsuspendし、```jobs```コマンドでmysqlが増えていることが確認できました。

```
❯ jobs
[1]  - suspended  vim ~/.vimrc
[2]  + suspended  mysql -u root -p
```

今度はMySQLとVimを交互に開いてみます。
```%1```、Ctrl-z、```%2```、Ctrl-z、```%1```、Ctrl-z …

![ctrlz3.gif](https://qiita-image-store.s3.amazonaws.com/0/73446/f6979020-625f-8907-4084-010138e2a418.gif)

または```%1```の代わりにbashなら```fg 1```でもOKです。(Zshだと ```fg %1```になります…)

# 自分の使い方
自分はそんなにたくさんサーバーにSSHする人ではないですが、1環境(サーバー)に対して1ウインドウ(tmuxなどのタブなど)開いておけばバックグラウンドで複数jobを立ち上げることで満足な感じになりました。

あと、バックグラウンドを使い始めると、気がついたら実はVimが複数立ち上がってたみたいなことが増えてくるので、最近はプロンプトにjob数を表示したりしてます。

<img width="425" alt="スクリーンショット 2018-08-29 0.15.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/73446/3f13b003-5828-3447-363b-fef66a6375a0.png">
一番右の1がjob数になっていて1つjobが立ち上がっていることがわかります。
設定はこんな感じです。

```zsh
local prompt_location="%F{081}%B%~%b%f"
local promot_mark="%B%F{208}%(!,#,$) %f%b"
local status_code="%(?,,%F{208} / %f%B%F{red}%?%f%b)"
local number_of_jobs="%(1j.%F{208} / %f%F{226}%B%j%b%f.)"

PROMPT="
${prompt_location}%B"'$vcs_info_msg_0_'"%b${number_of_jobs}${status_code}
${promot_mark}"
```
1行空行作ってプロンプトが入り、更に改行して常にコマンドが左から始まるようにしています。
(終了ステータスもnon-zeroのときに赤字ででます。vcs_infoは他の方の記事をご参考いただけると…！)
Vim乱立はこれでなんとか防げそうです…。

これで、tmuxやscreenを使うことができないような極限状態でも生き抜くことができるかもしれませんね…！

以上で共有は終わりです。
**みなさんのCLIライフが捗りますように！！**

## 追記: バックグラウンドプロセスの本来の使い方
fg と jobs は開発者のCLIが楽になるためだけにあると思われるといけないので、バックグラウンドプロセス本来の使い方についても少し触れて終わりたいと思います…。

バックグラウンドプロセスは本来、こういった方法よりも下記のような使われ方がメインです。

```zsh
$ ./too/heavy/process/take/a/long/long/time.sh &
```
最後に&を付けとくと、最初からバックグラウンド実行になり、実行の完了を待たずとも、次のコマンドを打ち込めるようになります。(nohupコマンドとセットで使われたりします。)

バックグラウンド実行しているものがいつ終わったのかについては、ログイン中であればシェルにそのまま出力されて終わりを知ることが可能です。

(↓1行目で実行して少し時間が経った際のスクショ(Zsh))
<img width="502" alt="スクリーンショット 2018-08-30 1.33.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/73446/efb6ae0d-d7bc-8569-fc8e-d7286af02c92.png">

また、Ctrl-zにてバックグラウンドに回した場合には、jobはサスペンド(停止中)になります。
なので sleep に & を付けるのではなく、Ctrl-zで抜けると今度は終了しません…。

(↓5秒以上待っても実行されないの図)
<img width="486" alt="スクリーンショット 2018-08-30 1.39.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/73446/ddb59518-ee5a-31da-ccb3-fdd18d470dd8.png">


そんなときには```bg```コマンドの出番です。バックグラウンドにしても動かしておきたい場合には下記のように指定します。

(↓↓Zsh で `bg %1`で動かしておく例。bash の場合は```bg 1```でOK)
<img width="643" alt="スクリーンショット 2018-08-30 1.43.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/73446/03124c1e-03e3-71dd-6c10-5212d7483fe5.png">

というわけで```fg```はフォアグラウンドで動かしておく(再開する)、```bg```はバックグラウンドで動かしておく、ということですね！

また、バックグラウンド実行は主にLinux上で動いているデーモンなどの処理もそれに当たるようです。
（今回、実際に使ってみたことでバックグラウンド実行についてイメージが湧きやすくなりましたね）

以上、今度こそ終わりになります！
ご清聴ありがとうございました。