FreeBSDでサービス(プロセス)の死活監視および自動再起動

#はじめに

FreeBSDでサーバを運用しているのですが、時々特定のサービス(プロセス)が異常終了するので死活監視をしたいと考えました。

> 補足: うちのサーバでよく異常終了するのは ripdというサービスです。Quaggaという経路情報を広報するサービスでripを広報するサービスです。異常終了するのはLAN内に正しくない経路情報が流れてる気がするんですが、詳細不明です。
 Ref: https://en.wikipedia.org/wiki/Quagga_(software)


#daemontools

FreeBSDのプロセスの死活確認で検索して最初に出てきたのは「daemontools」でした。

こちらを使おうかと思ったのですが、設定例を見てて難しいなぁと思って諦めました(^_^;　＜－根性無し。

Ref:  https://en.wikipedia.org/wiki/Daemontools

#超お手軽版

cronサービスで、監視対象のサービスのステータス (/usr/local/etc/rc.d/XXX status)を定期的に見に行って、異常なら再起動(/usr/local/etc/rc.d/XXX restart)させればいいんじゃないか？という考えが浮かびました。

XXの所は適切なサービス名に置き換えてください。また 「mail -s RESTART_XXX root」の「root」の所は適切な管理者のメールアドレスに書き換えてください。

```
$ crontab -l
3-59/5 * * * *  (/usr/local/etc/rc.d/XXX status || (/usr/local/etc/rc.d/XXX restart; echo RESTART XXX | mail -s RESTART_XXX root) ) > /dev/null 2>&1
```

とりあえずこれでも行けるんではと思います。killコマンドで監視対象サービスを強制停止させたら、再起動することは確認しています。実環境で異常終了した時に動作するかは確認していません。

注意事項: 多くの場合は問題ないとは思いますが、起動に時間がかかるサービスの場合、二重起動を起こしてしまう可能性があります。

#Monit

前述の超お手軽版をTwitterに張り付けて投函したら、とても良いツールを紹介していただきました。

> 15分で始めるmonitによるサーバ監視 
> http://shanon-tech.blogspot.com/2011/11/15monit.html?m=1

Ref: https://en.wikipedia.org/wiki/Monit
Ref: https://mmonit.com/monit/


##MonitのInstall
FreeBSDのPackageに含まれています。

```
$ pkg install monit
```

設定ファイルを作成してください。

```
$ cd /usr/local/etc
$ cp monitrc.sample  monitrc
$ vi monitrc
```

修正内容は以下のような感じでしょうか。「set mailserver」と「set alert」については各サーバの環境に合わせて修正ください。コマンドで「echo TEST | mail -s TEST root@localhost」と実行して管理者に「TEST」と書いてあるメールが届くなら、以下の設定のままで問題ありません。

あと、管理用のWebサーバは停止させてます。また監視対象のプロセス毎の設定ファイルは/usr/localの以下に変更しています。FreeBSDではpkgで導入したアプリケーションの設定は/usr/localに導入する場合がお作法のようですので。

```
$ diff -u monitrc.sample monitrc
--- monitrc.sample      2018-09-30 18:06:32.000000000 +0900
+++ monitrc     2019-06-03 17:10:13.801725000 +0900
@@ -80,6 +80,8 @@
 # set mailserver mail.bar.baz,               # primary mailserver
 #                backup.bar.baz port 10025,  # backup mailserver on port 10025
 #                localhost                   # fallback relay
+
+set mailserver localhost
 #
 #
 ## By default Monit will drop alert events if no mail servers are available.
@@ -139,6 +141,7 @@
 ## events by using a filter as in the second example below.
 #
 # set alert sysadm@foo.bar                       # receive all alerts
+set alert root@localhost

 #
 ## Do not alert when Monit starts, stops or performs a user initiated action.
 ## This filter is recommended to avoid getting alerts for trivial cases.
@@ -154,13 +157,13 @@
 ## commands to a running Monit daemon. See the Monit Wiki if you want to
 ## enable SSL for the HTTP interface.
 #
-set httpd port 2812 and
-    use address localhost  # only accept connection from localhost (drop if you use M/Monit)
-    allow localhost        # allow localhost to connect to the server and
-    allow admin:monit      # require user 'admin' with password 'monit'
-    #with ssl {            # enable SSL/TLS and set path to server certificate
-    #    pemfile: /etc/ssl/certs/monit.pem
-    #}
+#set httpd port 2812 and
+#    use address localhost  # only accept connection from localhost (drop if you use M/Monit)
+#    allow localhost        # allow localhost to connect to the server and
+#    allow admin:monit      # require user 'admin' with password 'monit'
+#    #with ssl {            # enable SSL/TLS and set path to server certificate
+#    #    pemfile: /etc/ssl/certs/monit.pem
+#    #}

 ###############################################################################
 ## Services
@@ -303,3 +306,4 @@
 #
 #  include /etc/monit.d/*
 #
+include /usr/local/etc/monit.d/*
```

監視対象のプロセス毎の設定ファイルのディレクトリを作成します。

```
$ mkdir /usr/local/etc/monit.d
```

/etc/rc.confに加筆します。

```/etc/rc.conf
monit_enable="YES"
```

##各サービス毎の設定ファイル

とりあえずisc-dhcpdの設定を挙げておきます。

だいたい以下の見様見真似でいいんじゃないでしょうか。 pidfileについては各サービス毎にファイルの名前を確認ください。/usr/local/etc/rc.d/のstartupスクリプトファイルを読めばだいたいわかります。

```/usr/local/etc/monit.d/isc-dhcpd(新規作成)
check process dhcpd with pidfile /var/run/dhcpd/dhcpd.pid
  every 2 cycle
  group dhcpd
  start program = "/usr/local/etc/rc.d/isc-dhcpd start"
  stop  program = "/usr/local/etc/rc.d/isc-dhcpd stop"
  if 5 restarts within 10 cycles then unmonitor
```

(修正2019/11/18: 「if 5 restarts within 5」を 「if 5 restarts within 10」に修正 )

次に、今回導入の発端となったripdの設定です。ripdはQuaggaのサブプロセスのため、ripd専用のstartupファイルは無いです。なのでQuaggaのstartupスクリプトを叩いています。またQuaggaの親プロセスのzebradの再起動も念のためしたいため、startupスクリプトの引数にrestartを渡しています。

```/usr/local/etc/monit.d/ripd(新規作成)
check process ripd with pidfile /var/run/quagga/ripd.pid
  every 2 cycle
  group quagga
  start program = "/usr/local/etc/rc.d/quagga restart"
  stop  program = "/usr/local/etc/rc.d/quagga stop"
  if 5 restarts within 10 cycles then unmonitor
```

以上で設定は完了です。monitを再起動させてください。

```
$/usr/local/etc/rc.d/monit restart
```

##動作確認

念のためプロセスをkillコマンドで強制停止してみてください。

例えば

```
$ pgrep "サービスのプロセス名"
```

とかでサービスのプロセス番号を確認し、

``` 
$ kill -KILL "上記で表示されたプロセス番号"
```

でサービスを強制停止します。

設定が正常なら、設定したメールアドレス(set alertで設定したメールアドレス)に警告のメールが届き、サービスが自動で起動すると思います。