MongoDB の dbpath を変更した時のトラブルシューティング

気軽に MongoDB のデータディレクトリを変更しようと思ったら `journalctl -xe` のメッセージから原因が特定しづらい上に、なかなか有力な情報も掴みづらく四苦八苦だったので解決までの道のりを共有します。

## 環境
- MongoDB 3.4.20 または 4.0.10
- CentOS 7.5

## 症状
`/etc/mongod.conf` 内の `dbpath` を変更して `systemctl start mongod` でスタートしようとすると以下のメッセージが表示されて失敗する。

```
Job for mongod.service failed because the control process exited with error code. See "systemctl status mongod.service" and "journalctl -xe" for details.
```

言われた通りに `journalctl -xe` をチェックしてもエラーの原因が非常にわかりづらいのが厄介です。

```
ERROR: child process failed, exited with error number 1
```

## 要約
以下の6項目を見直す必要があります。権限は、`mongod` ユーザーが読み書きできるよう設定されている必要があります。

- mongod プロセスが残留していないか
- ログファイルの権限
- dbPathの権限
- dbPath内にあるファイル・ディレクトリの権限
- pidファイルの権限
- sockファイルを一度削除する

## 確認方法

### プロセス確認
まず最初に `mongod` プロセスが残っていないか確認します。

```shell
$ ps -ef | grep mongod
mongod    45246      1  0 16:06 ?        00:00:02 /usr/bin/mongod -f /etc/mongod.conf
user      45611  22414  0 16:12 pts/0    00:00:00 grep --color=auto mongo
```

`/usr/bin/mongod -f /etc/mongod.conf` の行が `mongod` プロセスです。
`-f` オプションで設定ファイルを指定して起動しています。
`grep --color=auto mongo` は検索結果に関わらず表示されます。
残っていた場合は kill コマンド等で終了させてから再度 `mongod` のスタートを試みます。

```shell
$ sudo kill -15 プロセスID
$ systemctl start mongod
```
### ログファイルの確認

次にログファイルを確認出来るようにします。
デフォルトなら `/var/log/mongodb/mongod.log` にあるはずですが、なければ `mongod.conf` のpath行を確認します。

```shell
$ cat /var/log/mongodb/mongod.log
$ grep path /etc/mongod.conf
```

もう一度 `systemctl start mongod` を実行してログファイルの内容が変化するか確認します。
しないのであれば、このファイルの権限に問題がある可能性が高いです。mongod ユーザが読み書きできるよう修正します。

```shell
$ chmod 644 ファイル名
$ chown mongod ファイル名
```

ちなみに `mongod.log` の権限に問題があると `systemctl` ではなく `mongod` コマンドで実行した場合もエラーが発生します。

```shell
$ mongod --config /etc/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 42346
ERROR: child process failed, exited with error number 1
To see additional information in this output, start without the "--fork" option.
```

`/etc/mongod.conf` を編集して fork オプションを切ってからもう一度起動するとログファイルの権限に問題があると言われます。

```shell
$ sudo vi /etc/mongod.conf
```

```shell:変更前
fork: true
```

```shell:変更後
# fork: true
```

```shell
$ mongod --config /etc/mongod.conf
F CONTROL  [main] Failed global initialization: FileNotOpen: Failed to open "/var/log/mongodb/mongod.log"
```

### エラー確認と修正
`systemctl start mongod` で起動し、失敗したら `tail -n 20 mongod.log` でログファイルの確認します。
エラー内容に合わせて修正を加えます。エラー例を以下に記します。

#### 権限関連
mongod ユーザが読み書きが出来るよう権限を再設定する必要があります。

```shell
$ chmod 644 ファイル名
$ chown mongod ファイル名
```

- dbPathの権限

```
[initandlisten] exception in initAndListen: IllegalOperation: Attempted to create a lock file on a read-only directory: /var/lib/mongobk, terminating
```

- dbPath内にあるファイル・ディレクトリの権限

```
[initandlisten] Unable to read the storage engine metadata file: FileNotOpen: Failed to read metadata from /var/lib/mongobk/storage.bson
```

```
[initandlisten] WiredTiger error (13) [1559895370:747933][18875:0x7fe36a414b80], wiredtiger_open: __posix_open_file, 715: /var/lib/mongobk/WiredTiger.lock: handle-open: open: Permission denied Raw: [1559895370:747933][18875:0x7fe36a414b80], wiredtiger_open: __posix_open_file, 715: /var/lib/mongobk/WiredTiger.lock: handle-open: open: Permission denied
```

- pidファイルの権限

`/var/run/mongodb/mongod.pid` に書き込み出来ないと言われています。

```
[main] ERROR: Cannot write pid file to /var/run/mongodb/mongod.pid: Unknown error
```

#### sockファイル関連
- sockファイルを一度削除する

以下のメッセージの場合、 sock ファイルのパスは `/tmp/mongodb-27017.sock` です。

```
E NETWORK  [initandlisten] Failed to unlink socket file /tmp/mongodb-27017.sock Unknown error
WiredTiger error (1) [1559895679:626956][19170:0x7f2a81d8fb80], file:WiredTiger.wt, connection: __posix_open_file, 715: /var/lib/mongobk/WiredTiger.wt: handle-open: open: Operation not permitted Raw: [1559895679:626956][19170:0x7f2a81d8fb80], file:WiredTiger.wt, connection: __posix_open_file, 715: /var/lib/mongobk/WiredTiger.wt: handle-open: open: Operation not permitted
```

以上です。