Tomcat8 をリモートデバッグできるようにする

前回の投稿では、CentOS7 で Tomcat8 を自動起動するところまで進めた。今回は仮想マシンの Tomcat に対して、Windows マシンの Intellij からリモートデバッグできるようにしたい。なお、Intellij は Community Edition なので、Tomcat プラグインは利用しないこととする。

今回の投稿では一部で書籍「[詳解 Tomcat](http://www.oreilly.co.jp/books/9784873117058/)」の内容を参考にしている。Tomcat の深い部分を知るにはとても良い書籍だと思う。今回の投稿では Eclipse の設定については書いていないが、この本には書いてあるので Eclipse を使っている人は設定がわからなければ本を見て欲しい。

# systemd の設定

## ユニットファイルの作成

まずは CentOS 側に tomcat-debug というサービスを作成して、systemd を利用して起動・停止できるようにしたい。そのため、まずは systemd 用の service ファイル（`/etc/systemd/system/tomcat-debug.service`）を以下の内容で作成する。

```:/etc/systemd/system/tomcat-debug.service
[Unit]
Description=Apache Tomcat Servlet Container (debug)
After=syslog.target network.target

[Service]
Type=forking
EnvironmentFile=/etc/sysconfig/tomcat-debug
ExecStart=/opt/tomcat/apache-tomcat-8.0.17/bin/startup-debug.sh
ExecStop=/opt/tomcat/apache-tomcat-8.0.17/bin/shutdown.sh
SuccessExitStatus=0
KillMode=none

[Install]
WantedBy=multi-user.target
```

前回作成した `tomcat.service` との違いは以下のとおり。
* `EnvironmentFile` ではデバッグ用の環境変数を含んだファイルを指定している。
* `ExecStart` ではデバッグ用に異なる起動スクリプトを指定している。

## EnvironmentFile の作成

`/etc/sysconfig/tomcat-debug` を以下の内容で作成する。

```:/etc/sysconfig/tomcat-debug
JAVA_HOME="/opt/java/jdk1.8.0_31/"
JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"
JPDA_SUSPEND=y
JPDA_ADDRESS=8000
```

前回作成したファイルに３～４行目を追加している。

なお、Tomcat8 では、localhost 以外のマシンにリモートデバッグする場合は `JPDA_ADDRESS` を書く必要がある。書かない場合は listen する local address が localhost:8000 になるので、外部からの接続要求は拒否される。

## Tomcat 起動スクリプトの作成

リモートデバッグ用に Tomcat の起動スクリプトを作成する。

1. `/opt/tomcat/apache-tomcat-8.0.17/bin/startup.sh` をコピーして `startup-debug.sh` というファイル名で同じディレクトリに作成する。
2. `startup-debug.sh` の最後の行を `exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"` に変更する。`start` の前に `jpda` を付けただけ。
3. `start-debug.sh` に実行権限を付与する(`+x`)。

# firewalld の設定

ポート 8000 を開ける必要があるので、`/etc/firewalld/services/tomcat-debug.xml` を作成する。

```xml:/etc/firewalld/services/tomcat-debug.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Tomcat (HTTP) debug</short>
  <description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
  <port protocol="tcp" port="8000"/>
</service>
```

その後、以下のコマンドを実行する。

```
firewall-cmd --permanent --add-service=tomcat-debug
systemctl restart firewalld.service
```

# tomcat-debug サービスの起動

ここまでで準備は整ったので、tomcat をデバッグモードで起動する。その前に、すでに起動している Tomcat を停止する必要がある。

```
systemctl stop tomcat
```

その後、デバッグモードで Tomcat を起動する。

```
systemctl daemon-reload
systemctl start tomcat-debug
```

`tomcat-debug` は自動起動させないので、`systemctl enable` する必要はない。

# Intellij を利用したリモートデバッグ

ここからは Windows にインストールした Intellij IDEA Community Edition から仮想マシンの Tomcat にデバッグ接続する。

今回は、以下の手順を行う前に Tomcat のソースコードアーカイブをダウンロードして展開し、そのフォルダをプロジェクトとして Intellij で開いておく（特に難しくないはずなので割愛する）。自分自身の Web Application がある場合はそれを利用しても良い。

1. メニューから `Run -> Edit Configurations` を選択し、`Run/Debug Configurations` ダイアログを開く。
2. 左上の `+` ボタンをクリックして「`Remote`」を選択する。
3. Name には任意の名前を設定する。ここでは「`tomcat-debug`」とする。
4. `Configuration` タブの `Host` に「仮想マシンの IP アドレス」を設定し、`Port` に「8000」を設定する。
5. `OK` ボタンをクリックしてダイアログを閉じる。

![tomcat-debug.png](https://qiita-image-store.s3.amazonaws.com/0/59661/2da20377-caa9-1de7-b719-4593bc91a47e.png)

試しに「`org.apache.catalina.startup.Bootstrap`」クラスの「`main`」メソッドの最初のステップにブレークポイントを置いてから、メニューバーで「`tomcat-debug`」をデバッグ起動してみてうまくデバッグで中断できれば成功となる。

なお、理由はよくわかっていないが、一度デバッグを終えるたびに「`Rerun tomcat-debug`」を選択しないと次のリクエストでデバッグできなかった。この辺は改善できるのかわからないが、今後も調査していきたい（Intellij IDEA Ultimate Edition の Tomcat プラグインならこういうことは起こらないのかも？）。