WindowsでVagrantな仮想マシンをサービスとして常駐させる

# 経緯
VMをVagrantで管理している人はそれなりに居ると思う。特にWindowsユーザーの人には多いんじゃないかなぁーいくらWSLが最高とはいえ、不安になる点がいくつかあるのは事実だし。

で、そんなことをしていると思うことがあるわけでして。
「VagrantなVMを常駐させたい！」

ここ数年[ChinachuをVagrantで動かしている](https://yanoshi.hatenablog.jp/entry/2017/07/10/022843)のだが、再起動のたびに `vagrant halt` するのがかったるくて仕方がない。
厄介なのが `vagrant halt` せずにシャットダウンとかしちゃうと、VMがぶっ壊れてうまく動かなくなる事があったりもする(VirtualBox特有の症状なのかもだけど)
その昔、タスクスケジューラで同様のことをやろうとしたのだがうまく動いてくれなかった。おそらく「シャットダウンの前」ではなく「シャットダウン中」に動くためVirtualBoxが中途半端に終了しちゃっているんじゃないかと邪推している。

そんなこんなでNSSMでVagrantでのVM管理をサービス化しちゃおうという話。

# 概要
NSSMを入れて、適当に設定して、おしまい。
NSSMを本格的に利用したのは今回が初だが、これは「何でもサービス化しちゃう」という強力なツール。

勘所としては、「Vagrantで起動したVirtualBoxを掴み続ける」というのが予想以上に難しかったので、起動&動作を観察する的なbatを作って、これをサービスとして登録している。

試した環境は以下の通り。理論上はHyper-VなVMでも同じことができるとは思う。

- Windows 10 Pro for Workstations 1803
- VirtualBox 5.2.8
- Vagrant 2.0.4
- NSSM 2.24


# 下準備

## 各種batを準備
起動用とか終了用とかのbatたち。`Vagrantfile` と同じ階層に保存しておく。

### 起動&死活監視用bat
`start_and_check.bat`

```
cd /d %~dp0
C:\HashiCorp\Vagrant\bin\vagrant.exe up

@echo off
:loop
  curl http://localhost:20772  > nul
  if not %ERRORLEVEL%==0 goto :eof
  powershell sleep 10
goto :loop
```

`:loop` な部分に関しては環境に応じて見直すと良さそう。
SSHのポートをチェックする…とかでもいいのかもね。

### 終了用bat
`halt.bat`

```
cd /d %~dp0
C:\HashiCorp\Vagrant\bin\vagrant.exe halt
```


## NSSMをインストール
公式サイトがいつも不安定。この記事を書いているときはつながったけど、いつ繋がらなくなるかわかったもんじゃない…
[NSSM - the Non-Sucking Service Manager](https://nssm.cc/)

なので私はChocolateyで入れた。(Chocolateyのインストールがまだな人は[ここ](https://chocolatey.org/install)を参照)
[Chocolatey Gallery | NSSM - the Non-Sucking Service Manager 2.24.101.20180116](https://chocolatey.org/packages/NSSM)

```
choco install nssm
```

サクッとすぐ入る。管理者権限で動かした `cmd.exe` とかで `nssm` って打つとこんな感じ出てくる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/38f52d56-c084-041b-f5f2-f790ee10de19.png)


# 設定カキカキ
管理者権限で動かした `cmd.exe` とかで `nssm install xxxxx` を実行すると新規サービスが作れる。作ったサービスは `nssm edit xxxxx` で編集できる
私はChinachuを動作させるVMを動かしたかったわけなので以下のようにした。

```
nssm install chinachu
```

以下設定項目のスクショを貼り付けておく(ちなみにスクショは `nssm edit chinachu` で撮っているが、そこは気になさらず)


### Application
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/aac6b775-fb37-35e5-accf-5ab89aec88e1.png)
`Path` には起動用のbatを `Startup directory` には `Vagrantfile` が設置されているディレクトリをそれぞれ設定


### Details
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/7d4fbd3b-6ee9-06ee-f61f-2be2e47f80e1.png)
VirtualBoxが最低限必要としているサービスがいまいちわからなかったので、日和って遅延実行にしている。恐らく遅延実行じゃなくてもちゃんと動くとは思うけど…


### Log on
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/2924c793-2de4-da89-079d-449d266d5791.png)
ここ、ハマった。
`Log on as` はちゃんと設定しようね。


### Process
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/411f32ad-ce11-d12d-87dd-391d6007e67a.png)
`Console window` にチェックが入っていればそれで良さそう。

### Shutdown
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/826606a4-e90e-7f1a-b434-51ebdd9ba04f.png)
雑だけど、とりあえずこれで動いている。

### Exit action
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/3a671ef6-f142-94db-563c-5b54476a2385.png)
`Restart application` にしてある。

### I/O
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/53948748-72ed-aa49-6a27-318e2f9fcf34.png)
特に必須じゃないけど、デバッグとかをしたいのであれば設定しておくとログがファイルに書き出されるので便利。

### Hooks
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/05b595e8-c8ca-f0cc-f76d-abf4887fdeaf.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/d0c39995-dbde-084d-8559-9330099b5957.png)

`Service stop` と `Application exit` にそれぞれ終了用batを設定している

# 動作確認
いぇーい

![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/16cb0053-63f3-c283-a587-9dc2cb79b033.png)


# 所感
NSSMは便利。


# 余談
ちなみに上記で動かしたVirtualBoxなVMはなぜかマネージャーから眺められない。
変な方法で起動しているからなのかなぁ…
`Vagrantfile` で定義したプロビジョナーで全部設定を済ませてしまって以後いじらない…みたいな使い方をしているといいのかもだけど `vagrant ssh` とかができない。
今のところ私は支障をきたしてはいないので、まぁいいかなーと割り切って詳しく調べてはないけど、使い方によっては結構不便なのかも。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/133666/a73be39f-0534-72a2-1e15-fbf2e3958adc.png)

恐らく実行タイミング or 実行ユーザーが何かしらの原因なんじゃないかと邪推しているけど、真相は不明。