前回はdummyプログラムを用いたサービスの登録方法について説明しました。
今回は、その登録したサービスを監視し異常発生時の再起動を自動的に行いたいと思います。
dummyプログラムは、TCP/IPによる通信を行うサーバ側のプログラムです。
ポート番号10050を使用してクライアントからの接続を待っています。
そのdummyプログラムが異常終了しゴースト化してしまっていたり、プロセス自体が動作していない状態(psコマンドで見つからない時)に、自動的に再起動を行わせます。
準備
プロセスの監視には色々と方法がありますが、今回はmonitを使用します。
monitのインストール
まず最初に、epelリポジトリをインストールします。
デフォルトではインストールされていないので、準備します。
# yum -y install epel-release
続けて、monitをインストールします。
# yum -y install monit
これだけです。
monitの初期設定
色々と他のサイトでも紹介されている様なので、今回は細かな設定については割愛します。
私がやったことは、以下の通りです。
1)monit.confの設定変更
/etc/monit.confもしくは/etc/monitrcの記述内容を編集します。
当該ファイルの一番下にこんな記述があります。
###############################################################################
## Includes
###############################################################################
##
## It is possible to include additional configuration parts from other files or
## directories.
#
include /etc/monit.d/*
#
このままでは、/etc/monit.d/にある全てのファイルがインクルードされることになります。
/etc/monit.d/には各監視対象毎の設定ファイルが置かれることになります。
そこで、以下の様に編集しました。
###############################################################################
## Includes
###############################################################################
##
## It is possible to include additional configuration parts from other files or
## directories.
#
#include /etc/monit.d/*
include /etc/monit.d/*.conf
#
/etc/moni.d/*.confとすることで、拡張子が.confのファイルだけが対象となります。
この設定を行う場合には、以下の作業も忘れずに行って下さい。
初期状態では、/etc/monit.d/にあるファイルはloggingだけになっています。
# ls -la
合計 xx
drwxr-xr-x. 2 root root 78 2月 6 10:48 .
drwxr-xr-x. 152 root root 12288 2月 5 19:58 ..
-rw-r--r--. 1 root root 51 9月 13 2015 logging
loggingファイルをlogging.confにコピーします。ファイル名の変更でも構いません。
cp -p /etc/monit.d/logging /etc/monit.d/logging.conf
これでmonitが動作する環境設定は準備出来ました。
それでは、monitをサービスとして起動します。
# systemctl start monit
OS起動時に自動起動させるためには更に以下のコマンドを実行する。
# systemctl enable monit
これで監視が行われる状態になっています。
でも、監視対象が何も指定されいませんので、以下でdummyサービスの監視を行います。
プロセスの監視
前回の設定ではサービスとして登録しましたが、ここでは敢えて単独のプロセスとして監視対象にしました。
サービスとして登録した場合の方法については、別途記載しています。
サービスと登録している状態で、この方法を取ることはお勧めできません。
方法が異なる起動方法によりプロセスが再起動する可能性が発生し、管理上良くないからです。
この方法を採用する場合には、サービスとしての登録は行わない方が賢明です。monit単独で利用されることが望ましいと判断します。この方法とサービスでの起動を両方採用することは、二重起動を引き起こす可能性を含んでいます。
多分、プログラムは正常に動作しますが、異常が発生した場合に何が原因なのか特定することが困難になる気がします。
/etc/monit.d/dummy.confを以下の内容で作成します。
check process dummy matching "dummy"
start program = "/hogehoge/dummy"
stop program = "/usr/bin/kill -9 dummy"
if failed port 10050 then restart
if 10 restarts within 10 cycles then unmonitor
1行目:監視対象を指定します。
2行目:起動方法を指定します。
3行目:終了方法を指定します。
4行目:異常時の処置を指定します。今回はポート10050を使用しており、10050ポートが開いているかどうかを確認しています。
5行目:10回再起動をトライしてダメだったら再起動を取止めるという内容で、再起動の試行回数を指定しています。
後は、monitに設定を読込ませれば完了です。以下のコマンドでmonitに設定内容を読込ませます。
# monit reload
以上で完了です。
監視状況を確認するには以下のコマンドで確認出来ます。
# monit status
サービスの監視
サービスの監視も基本的には同じです。
設定ファイルが以下の通り変更になりますが、実際には同じでも大丈夫です。
サービスとして登録する方法は前回を参考にしてください。
check process dummy matching "dummy"
start program = "/usr/bin/systemctl start dummy"
stop program = "/usr/bin/systemctl stop dummy"
if failed port 10050 then restart
if 10 restarts within 10 cycles then unmonitor
プロセスと異なり、systemctlを使用して起動と停止を行っています。
起動時にsystemctlコマンドを使用することで、サービス側との二重起動が避けられます。PIDはSystemd側で管理されていますので、Systemdを経由した起動の方が都合が良いわけです。
dummyプログラムのPIDを調べれば解ることなので、pkillやkillを使用して停止させることも出来るのですが、Systemd側における管理が煩雑になることを避ける意味から、systemctlコマンドを使うことになります。
サービス登録をしてRestartによる再起動を行った場合は、ポートの状態までは監視してくれませんでしたが、monitを使うことでポートの監視を行える様になっています。
ただし、固定のポートアドレスをハードコーディングで行う必要があるため、ちょっと使い勝手が良いとは言えません。
尚、この場合にはサービス登録側の設定も少し変更した方が良いでしょう。
こんな感じになります。
[Unit]
Description = Dummy TCP daemon
[Service]
#Restart = always
StartLimitInterval=60
StartLimitBurst=5
ExecStart = /hogehoge/dummy
ExecStop=/usr/bin/kill -9 $MAINPID
[Install]
WantedBy=multi-user.target
プロセスとして登録した場合とサービスとして登録した場合を敢えて記載しましたが、monitだけで十分では無いか?と考えると思います。通常はmonitだけで十分だと私も思います。
サービスとして登録する意味があまりある様には思えません。
敢えてサービスとして登録する意味はと言えば、一意のファイル名でプログラムが作成されていれば良いのですが、同名の実行ファイル名でプロセスが起動する様な場合には、サービスにしておく意味がある・・・と言うことぐらいでしょうか?
更に突っ込んで!monitが死んだら?
サービスで登録した場合でもプロセスとして登録した場合でも同じことなのですが、monit自体が死んでしまったら、プロセスを再起動することが出来ません。
CentOS 7では、UpStartの設定に従来の/etc/initが使えません。
ということで、/usr/lib/systemd/system/monit.serviceを変更します。
[Unit]
Description=Pro-active monitoring utility for unix systems
After=network.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/monit -I
ExecStop=/usr/bin/monit quit
ExecReload=/usr/bin/monit reload
[Install]
WantedBy=multi-user.target
[root@localhost system]# pwd
/usr/lib/systemd/system
Restart=alwaysを追加しただけです。
これで、自動的に再起動を行ってくれます。