Knowledgeで通知メールが送信されない時の対処（Linux）

# 「Knowledge」とは

これです。
https://support-project.org/knowledge_info/index

オープンソースのナレッジベースシステムで、Java8・Tomcat8で動きます。

# 現象

メール送信設定を適切に行い、テストメールも送信できる。
それなのに、ユーザ承認依頼や新着記事通知のメールは一向に飛びませんでした。

https://github.com/support-project/knowledge/issues/412
によれば、

> メール通知は、tomcatで動いているweb appから、定期的にjavaのバッチプロセスを起動して送信しています。

とのことです。
テストメールが問題なく送信されるのは、バッチプロセス経由ではないからのようです。

# 対処

上記のissueへの開発者からのコメントを読む限り、以下の4つのJavaクラスを実行すればメールが無事送信されるようです。

```
org.support.project.knowledge.bat.FileParseBat
org.support.project.knowledge.bat.MailSendBat
org.support.project.knowledge.bat.WebhookBat
org.support.project.knowledge.bat.NotifyMailBat
```

これらのクラスは`/opt/tomcat/apache-tomcat/webapps/knowledge/WEB-INF/classes`の中にあります。

実行するといっても、都度手動で実行するわけにはいかないので、cronの出番となりました。

## 実行スクリプトを書く

以下、自環境のtomcatは`/opt/tomcat/apache-tomcat/`にあることが前提です。
tomcatユーザのホームディレクトリも上記ディレクトリと同じです。

tomcatユーザで動かすつもりなので、実行スクリプトはtomcatホームディレクトリに作成しました。

```sh:/opt/tomcat/apache-tomcat/knowledge-mail.sh
#!/bin/sh

JAVA_HOME=/usr/java/latest
PATH=${JAVA_HOME}/bin:${PATH}

KNOWLEDGE_HOME=/opt/tomcat/apache-tomcat/.knowledge
BASEPATH=/opt/tomcat/apache-tomcat/webapps/knowledge/WEB-INF
CLASSPATH=${BASEPATH}/classes:${BASEPATH}/lib/*

cd ${KNOWLEDGE_HOME}/logs

${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.FileParseBat
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.MailSendBat
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.WebhookBat
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.NotifyMailBat
```

パスについては、cronで読み込まれる環境変数はアテにならないという前知識があったため、すべて明示しています。特にjavaについてはJava8でなければ動かないので、パスを明示しました。

最後に、このスクリプトに実行権限を与えることを忘れてはいけません（忘れてた）。

## cronに登録

`crontab -u tomcat -e`でtomcatユーザのcrontabのエディタを起動し、以下を追加します。

```sh:
*/5 * * * * /opt/tomcat/apache-tomcat/knowledge-mail.sh
```

実行結果が心配だったので、`>> /opt/tomcat/apache-tomcat/knowledge-mail.log 2>&1`を末尾に追加して、実行結果をファイルで確認しながら動作確認を行いました。

`*/5`は5分おきを表しており、今後の運用次第で適宜変更すると思います。

## 結果

ユーザ承認依頼や新着記事通知のメールがきちんと送信されるようになりました。

# 動かない場合の心当たりについて

自分が引っかかったところとしては、

- 実行スクリプト
    - 1.8以降のJavaが実行しているか？
- パーミッション関係（tomcatユーザが書き込めるか）
    - 実行スクリプト
    - /opt/tomcat/apache-tomcat/.knowledge/logs/
    - /opt/tomcat/apache-tomcat/.knowledge/app.log

あたりです。

この対応を行う前に、Knowledgeのシステム設定内>メール送信設定の内容（特に認証周り）がシロか？という切り分けが必要とは思いますが、それはテストメール送信で容易に検証できると思うので、引っかかることはないかと思います。

# 原因は不明

なぜバッチプロセスが正常に動いてくれていないのかは、分かっていません。
warファイルを設置しただけなので、環境面において何かしらの不備があったのかもしれません。

# 動作環境

- Knowledge: v1.5.0 Pre1
- Tomcat：8.0.36
- JDK：8.0_91
- CentOS: 6.7

# (2017.03.09追記) 満期処理も行われるように修正

導入当初から、
「ログファイルの満期処理、いつまで経っても行われないな～」
と思っていました。

満期処理と言ったらバッチだろうと思い、Cron周りの処理を行っているソース（org/support/project/knowledge/listener/CronListener.java）を確かめたところ、実行されていないバッチがもう2つあることがわかりました。

- org.support.project.knowledge.bat.KnowledgeFileClearBat (1時間間隔）
- org.support.project.knowledge.bat.FileParseBat (5分間隔)
- org.support.project.knowledge.bat.MailReadBat (3分間隔)
- org.support.project.knowledge.bat.MailSendBat (3分間隔)
- org.support.project.knowledge.bat.WebhookBat (3分間隔)
- org.support.project.knowledge.bat.NotifyMailBat (3分間隔)

以前はKnowledgeFileClearBatとMailReadBatを実行していませんでした。
満期処理はKnowledgeFileClearBatが担当しているようで、これが実行されない限りは延々とログファイルが増えていくばかりなんですね。

というわけで、本来の実行間隔も加味して、スクリプトを分割したり修正したりしました。

```sh:/opt/tomcat/apache-tomcat/knowledge-mail.sh
#!/bin/sh

JAVA_HOME=/usr/java/latest
PATH=${JAVA_HOME}/bin:${PATH}

KNOWLEDGE_HOME=/opt/tomcat/apache-tomcat/.knowledge
BASEPATH=/opt/tomcat/apache-tomcat/webapps/knowledge/WEB-INF
CLASSPATH=${BASEPATH}/classes:${BASEPATH}/lib/*

cd ${KNOWLEDGE_HOME}/logs

${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.MailSendBat
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.WebhookBat
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.NotifyMailBat
${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.MailReadBat
```

```sh:/opt/tomcat/apache-tomcat/knowledge-parse.sh
#!/bin/sh

JAVA_HOME=/usr/java/latest
PATH=${JAVA_HOME}/bin:${PATH}

KNOWLEDGE_HOME=/opt/tomcat/apache-tomcat/.knowledge
BASEPATH=/opt/tomcat/apache-tomcat/webapps/knowledge/WEB-INF
CLASSPATH=${BASEPATH}/classes:${BASEPATH}/lib/*

cd ${KNOWLEDGE_HOME}/logs

${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.FileParseBat
```

```sh:/opt/tomcat/apache-tomcat/knowledge-clear.sh
#!/bin/sh

JAVA_HOME=/usr/java/latest
PATH=${JAVA_HOME}/bin:${PATH}

KNOWLEDGE_HOME=/opt/tomcat/apache-tomcat/.knowledge
BASEPATH=/opt/tomcat/apache-tomcat/webapps/knowledge/WEB-INF
CLASSPATH=${BASEPATH}/classes:${BASEPATH}/lib/*

cd ${KNOWLEDGE_HOME}/logs

${JAVA_HOME}/bin/java -classpath ${CLASSPATH} org.support.project.knowledge.bat.KnowledgeFileClearBat
```

もちろんcronの登録内容も修正します。

```sh:
*/3 * * * * /opt/tomcat/apache-tomcat/knowledge-mail.sh
*/5 * * * * /opt/tomcat/apache-tomcat/knowledge-parse.sh
*/60 * * * * /opt/tomcat/apache-tomcat/knowledge-clear.sh
```

これで本来の動きにかなり近くなったはずです。