tkuchikiの日記

新ブログ https://blog.tkuchiki.net

Monit でログを監視してプロセスを再起動させる

Monit を使って、
ログに特定の文字列が書き込まれた時にプロセスを再起動させる例です。

以下の要件を満たすために検証しました。

  • 原因を調べきれていないけれど時々セグフォしてしまう
  • ずっと落ちたままだと困るので再起動させたい
  • 数分で起き上がってくれれば特に問題ない

例として httpd を再起動させるものとします。

検証した Monit のバージョン

今回検証したのは、Monit 5.1.1 です。

Install Monit

epel repo を追加した状態で以下を実行。

yum install -y monit

最新版から離れているので、最新版を使いたい場合はビルドしたほうが良いです。
自動起動の設定をしておきます(設定ファイルを追加するので、まだ起動しない)。

chkconfig monit on

Monit 設定ファイル

Default では、/etc/monit.d/以下のファイルを include するようになっているので、
以下を /etc/monit.d/httpd として追加。

check file messages with path /var/log/messages
    if match "segfault" then exec "/usr/local/bin/httpd_restart"

構文の説明は以下のとおりです。

check file <unique name> with path <file path>

- check file <unique name>
    -> ファイル監視をする、<unique name> はその名のとおり、重複しない任意の名前で良い
- with path <file path>
    -> <file path> のファイルを監視
if match {regex|path} then <action>

- if match {regex|path}
    -> 正規表現か、正規表現を列挙したファイルの絶対パスを指定
- then <action>
    -> 任意の action を指定(今回は exec)
        => exec は指定したスクリプトを実行する action

これらを踏まえると設定した監視の条件は、
「/var/log/messages に segfault という文字列が書き込まれたら /usr/local/bin/httpd_restart を実行する」
となります。

プロセスを再起動するスクリプト

今回のケースでは、セグフォすると service restart ができなかったので、
kill -KILL でプロセスを殺してから service start しています。
service restart が使える場合は、そちらのほうが良いでしょう。

#!/bin/bash

set -e

MSG="httpd force restarted."

kill -KILL $(pidof httpd)
rm -f /var/run/httpd/httpd.pid
service httpd start

logger -p local0.info $MSG -t "Monit"

上記スクリプトを /usr/local/bin/httpd_restart に配置します。
(chmod +x /usr/local/bin/httpd_restart も忘れずに)

Start Monit

service monit start

実験

/var/log/messages に対象となる文字列を追記します。

echo "segfault" >> /var/log/messages

しばらくすると、/var/log/monit に以下のようなログが流れます。

[JST May  7 13:01:54] error    : 'messages' content match [segfault]
[JST May  7 13:01:54] info     : 'messages' exec: /usr/local/bin/httpd_restart

再起動したか一見わからないので、
以下の様なコマンドを実行してプロセスの起動時間を確認します。

ps -eo pid,ppid,lstart,cmd | grep httpd

起動時間が直近になっていれば成功です。

まとめ

Monit でログを監視して、プロセスを再起動する例を示しました。
正規表現を使った柔軟なログ監視ができるので、使えるケースは多そうです。