tmuxで簡単に複数ジョブのバックグラウンド実行を実施

## はじめに
こういうテーマの記事をqiitaに書くのは初めての気がします。
業務でウン十年ぶり？にLinuxのコマンドを触っているわけですが、タイトルのような課題があり、tmuxをいうツールを使うと簡単にできるので、その手順を以下に記載します。
目的としては、次の2点です。

* 対象Linuxはクラウド上のサービス。ssh接続をするが、長時間のバッチなので、sshのセッションを切っても、バッチ自体は動いていてほしい
* 複数のバッチを同時に動かす。それぞれのコンソール出力は個別に確認したい

私のウン十年前の知識では、nohupを使うのが、バックグラウンド実行の王道だったわけですが、確か、この場合はコンソール出力は/dev/nullに捨てていたはず。
tmuxであれば、コンソール出力も個別に確認可能です。

## 導入
試しに次のコマンドを打ってみてください。

```
$ tmux -h
```

こんな結果が返ってくれば、すでにtmuxが導入済みなので、導入のステップはスキップしていいです。

```
tmux: unknown option -- h
usage: tmux [-2CDlNuvV] [-c shell-command] [-f file] [-L socket-name]
            [-S socket-path] [-T features] [command [flags]]
```

未導入であった場合は、次のコマンドで導入してください。

### Debian/Ubuntu 系
```
$ sudo apt-get install tmux
```

### Red Hat/CentOS 系
```
$ sudo yum install tmux
```

### (参考)　macOS (Homebrew を使用)
```
$ brew install tmux
```

## 準備

### 概念理解
初めて使う場合に戸惑うのがtmux固有の概念です。次の3階層の管理単位があり、起動したいバッチプロセスはウインドウ単位でもペイン単位でも実行可能です。

**セッション**: 最上位の管理単位です。セッションごと全プロセスの削除ができるので、複数種類のジョブを同時に動かす場合はセッションを別にする使い方が考えられます。

**ウインドウ**: セッションの子供になる管理単位です。以下のサンプルでは、複数ウィンドを使う形になります。

**ペイン**: ウインドウの更に子供の管理単位です。しかし、どういう使い方があるのかは正直わからなかった。少なくとも今回の利用目的では意識しなくてよかったです。

普通の使い方の場合、1セッション、複数ウインドウで十分と思われ、以下のサンプル手順はそれを実現するためのものとなります。

### サンプルバッチコード
以下の手順では、下記のサンプルバッチコードを利用します。
無限ループを回りながら10秒に一回コンソール出力をする単純なものです。

事前にdummy-job.shとして作成し、実行権をつけておいてください。

```
#!/bin/bash

x=0  # 初期値を設定
z=$1 # バッチを区別するため呼び出し時のパラメータも表示

while true; do
    x=$((x + 1)) # x をインクリメント
    y=`date`  　　　　　# timestampを取得
    echo $z $x $y   # 画面表示
    sleep 10     # 10秒待機
done
```

## 利用シナリオ
上で定義したdummy-job.shを5パラでパラメータだけ変えて起動します。その後で、一度sshのセッションを切ります。
再度、ssh接続し、5つのジョブのコンソール出力が全部確認できたら、目的達成とします。

以下の手順では、batch-sessionという名前のセッションを作り、このセッションの配下のウインドウから個別にdummy-job.shを起動します。


### バッチ起動手順

#### tmux セッションの開始
次のコマンドで、tmuxセッションを開始します。

```
$ tmux new -s batch-session
```

コンソール画面最下部に下の赤枠のような行が表示されていれば、起動に成功しています。
ちなみに、黒塗りの箇所はホスト名とか表示されている箇所で、身元を隠すためにこういう形にさせていただいています。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/3b3985a0-a4fb-2845-7edc-78032f11753d.png' width=800>

#### 新規ウィンドウの作成
この状態で、**ctrl+b c**を入力します。

ちょっとわかりにくいですが、一番下の行のステータスがこんな形に変化します。


<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/06f4477a-899f-c94d-9e0c-8ad7a780d26a.png' width=500>

この状態で、次のコマンドを実行してください

```
$ ./dummy-job.sh test01
```

これで、最初のバッチ起動に成功しています。
つづいて、今の操作を4回繰り返してください。
バッチ起動のパラメータは、test02などと変化させていきます。

下記が、初回を含めて5回繰り返した後のステータス行です。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/cb17e595-454c-73f2-238f-2651e1b0e904.png' width=800>

赤枠で囲んだところに、1:bashから5:bashが並んでいて、5個のジョブが動いていることが確認できます。

### 動かしたいバッチプログラムが1つだけの場合
上の手順は、動かしたいバッチプログラムが複数ある場合です。
動かしたいバッチプログラムが1つだけの時は、**ctrl+b c**でウインドウを作る必要もなく、セッション起動直後にバッチコマンドを実行すればOKです。
その場合、次のステップの状況確認も不要で「セッションから抜ける」を実施すればいい形になります。

### 状況確認
この状態で、**ctrl+b w**を入力してください。稼働中のバッチの一覧が表示されます。
下記は、矢印キーを何回か押して、最初に起動したバッチに選択対象を変更したときのものです。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/370cc1bc-d237-3101-102a-e573872df000.png' width=800>

### セッションから抜ける
セッションから、外に出るためには
**ctrl+b d**を入力します。

抜けた状態で次のコマンドを打つと、ダミーのバッチが5つ平行で動いていることが確認できます。

```
$ ps auxw | grep dummy | grep -v grep
```

```
ubuntu     10795  0.0  0.0   7892  3584 pts/2    S+   10:20   0:00 /bin/bash ./dummy-job.sh test01
ubuntu     10844  0.0  0.0   7892  3712 pts/3    S+   10:21   0:00 /bin/bash ./dummy-job.sh test02
ubuntu     10878  0.0  0.0   7892  3712 pts/4    S+   10:22   0:00 /bin/bash ./dummy-job.sh test03
ubuntu     10916  0.0  0.0   7892  3712 pts/5    S+   10:22   0:00 /bin/bash ./dummy-job.sh test04
ubuntu     13306  0.0  0.0   7892  3584 pts/6    S+   10:39   0:00 /bin/bash ./dummy-job.sh test05
```

この状態になっていれば、sshセッションと関係なく、5つのバッチは動いているので、sshを抜けてもバッチは止まりません。
それを確認するため、一度ssh接続を切ってください。

### 接続再開

ssh再接続後に念のため、上のコマンドを実行してみます。5つのバッチは動き続けているはずです。
tmuxのセッションに再度入るためには、次のコマンドを実行してください。

```
$ tmux a
```

先程のリスト表示画面に戻ったのがわかると思います。**ctrl+b d**で再度セッションを抜けてください。


### 全ジョブ停止
最後にセッションに紐付いた全ジョブ停止のコマンドを説明します。

```
$ tmux kill-session -t batch-session
```

このコマンド実行後に改めて

```
$ ps auxw | grep dummy | grep -v grep
```

を実行すると、すべてのジョブが終わっていることが確認できます。

## 参考リンク
これ以外の細かいコマンドについては、以下の記事を参考としてください。

https://www.tohoho-web.com/ex/tmux.html