Aqutras Members' Blog

株式会社アキュトラスのメンバーが、技術情報などを楽しく書いています。

hubot-slackで `INFO Slack client closed, waiting for reconnect` がSlack連携が切断される問題への対処法

はじめに

お久しぶりですvitaminです。
アキュのブログでは技術ネタしか書いていないので、そろそろネタが切れそうです。
先日、社内用hubotの改良を行った際のことがネタになりそうだったので書かせて頂きます。

アキュトラスのhubot

先日のリモートワークのススメ - Aqutras Members' Blogでも簡単に紹介していましたが、アキュトラスでは、社内での連絡にslackを利用しています。
殆どの仕事のやりとりをslackを通じて行うため、Githubやesaなどの情報がslackを通じて確認出来る方が何かと都合がいいことが多いです。
そこで、hubotを運用して、各種サービスとslackを連携させることで、作業や話し合いの効率化を図っています。

hubot-slackの問題点

hubotとslackの連携には、hubot-slack を利用しています。
このライブラリは簡単にslack連携や動作ルールを記述することができ、便利なライブラリです。
しかし、このライブラリを使ってslackと連携を行っている場合、たまに、以下のログが出力されたあと、slackとの連携が切断されるということが起こります。

INFO Slack client closed, waiting for reconnect

これがどういう条件で発生するのかは不明なのですが、これが発生した後は、slackから何を投げても反応しなくなり、hubotの再起動が必要になります。
この問題は、issue #203としても報告されているようですが、まだ対応には至っていないようです。

incronを利用した対処

どうやら原因は根が深そうなので、根本的な解決は諦めて、接続が切断されたら自動で再起動する、という方法で対処したいと思います。
これには、incronを利用します。その名の通りcronと似たような仕組みなのですが、cronが一定時間毎にジョブを実行させるのに対し、
incronはファイルの変更などのイベントに対してジョブを実行します。
incronは、ユーザごとにテーブルを持ち、そのユーザの権限でファイルの監視やコマンドの実行を行います。
incronについては、以下のブログ記事が分かりやすかったです。 qiita.com

incronでのhubotの自動再起動

まず、hubotの自動再起動用スクリプトを用意します。
今まで、接続が切断された時は、必ず最後の1行がINFO Slack client closed, waiting for reconnectとなっています。
そのため、最後の行にSlack client closedという文字列があれば、hubotを再起動するという形で作成したいと思います。
弊社のhubotは、/etc/init.d/hubot に起動スクリプトを配置し、サービス化しているため、これを用いて再起動を行います。
簡単ではありますが、以下の様なスクリプトを記述しました。

tail -n 1 /var/log/hubot.log | grep 'Slack client closed' > /dev/null

if [ $? -eq 0 ]; then
  /etc/init.d/hubot stop && /etc/init.d/hubot start
  sleep 5
  echo 'auto restart from incron !' >> /var/log/hubot.log    
fi

hubotの起動から、slackへの接続までは多少時間がかかるので、5秒ほど待機した後、ログにリスタートしたことを書き込んでいます。 これを、/usr/local/bin/hubot_auto_restartとして配置します。

次に、incronで、hubotのログファイル(/var/log/hubot.log)が変更された時にこのスクリプトを実行できるようにしたいと思います。
hubotはサービス化しており、startとstopはrootでないと実行できないようにしているので、rootのincronテーブルを編集します。

$ su - root
# incrontab -e

変更を監視するには、IN_MODIFYイベントを監視するように設定します。
以下のように監視イベントを記述します。

/var/log/hubot.log IN_MODIFY /usr/local/bin/hubot_auto_restart

そして、incronの変更を適用させます。

incrontab -d

手動でログファイルに、接続切断の際のSlack client closedを投げると、hubotが再起動されると思います。

echo 'Slack client closed' >> /var/log/hubot.log

おわりに

hubotの問題を、hubotの技術だけで解決するのではなく、incronという全く別の仕組みを利用して対処しました。
根本的な問題は解決できていないですが、時間がなかったり、解決できそうにない場合は、他の技術を組み合わせて、さっさと解決してしまうに限ります。
もしこの問題が解決できたらOSSにコミット出来るチャンスです!!