※2016/01/26 13:00
そもそも、systemdだったら依存関係についてAfterやBefore、Requestがあることに気づいた。こんな回りくどいことしなくてもよさそうなので、2016/01/27に追記・修正を行っている。
仕事で、特定のプロセスが落ちたら強制的にそのプロセスを前提として動作しているサービスも落とす必要が出てきたので、どうにか実現できないか調べてみた。
そしたらCentOS7で採用されているsystemdでは、プロセスの依存関係について記述出来るようなので、それで実現することにした。
基本的には、「.service」ファイルの[UNIT]項目に、以下の項目で依存関係のあるサービス名やターゲット名を記述する。
- Requires… ここで指定したUNITが動作していない場合、このUNITを起動させない。指定したUNITが停止した場合はこのUNITも停止させる。(並行起動させることができるので、通常は後述するBefore/Afterと組み合わせる)
- Conflicts… このUNITが動作中は、ここで指定したUNITは起動させない。起動している場合は停止処理を実施する。
- Wants… UNITが起動する際、ここで指定したUNITも起動させる(強制力なし)
- Before… このUNITが起動した後に、ここで指定したUNITを起動させる
- After… このUNITが起動する前に、ここで指定したUNITが起動されている必要がある
- Condition*… 指定した条件を満たした場合のみ起動する
これで、連動してサービスの起動・停止を実施できる。
対象のプロセスのデフォルトがGracefulの場合
対象のプロセスがスグ落ちるプロセスならいいんだけど、Gracefulで停止するプロセスの場合だとうまくいかない事がある。
そんな場合は、systemdでサービスを管理させるファイル「/usr/lib/systemd/system/サービス名.service」に、ExecStopPostとしてコマンドを記述する事で、異常終了を含むサービス停止時にそのコマンドを流す事が出来る。
つまり、この項目にkillコマンドを記述すればよい。
例えば、maxscale.service(上がってないといけないプロセス)に以下のように記述することで、プロセス停止時にhttpd(maxscaleを前提として動作するプロセス)サービスを停止させることが出来る。
(ここではsystemctlから停止させているけど、すぐにでも停止させるなら「kill -KILL $(pgrep プロセス名)」で指定したほうがいいこともある。状況に応じて使い分けるとよいだろう。)
●/usr/lib/systemd/system/maxscale.service
[Unit]
Description=MariaDB MaxScale Database Proxy
After=network.target
[Service]
Type=forking
Restart=on-failure
PIDFile=/var/run/maxscale/maxscale.pid
ExecStart=/usr/bin/maxscale --user=maxscale
ExecStopPost=/bin/sh -c 'systemctl stop httpd'
[Install]
WantedBy=multi-user.target
さて、それでは実際に動作をみてみよう。
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
root 26540 1 0 18:12 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26541 26540 0 18:12 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26542 26540 0 18:12 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26543 26540 0 18:12 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26544 26540 0 18:12 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26545 26540 0 18:12 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
maxscale 26552 1 0 18:13 ? 00:00:00 /usr/bin/maxscale --user=maxscale
[root@localhost ~]#
[root@localhost ~]# kill $(pgrep maxscale)
[root@localhost ~]#
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
[root@localhost ~]#
確かに、無事停止する事が出来た。
killで落としても動作するので、プロセスが落ちる等の障害時に使えるだろう。
ただ、一つ注意点が。。。
[root@localhost ~]# systemctl start httpd
[root@localhost ~]# systemctl start maxscale
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
root 26748 1 1 18:19 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26749 26748 0 18:19 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26750 26748 0 18:19 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26751 26748 0 18:19 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26752 26748 0 18:19 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 26753 26748 0 18:19 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
maxscale 26760 1 2 18:19 ? 00:00:00 /usr/bin/maxscale --user=maxscale
[root@localhost ~]#
[root@localhost ~]# systemctl restart maxscale
[root@localhost ~]#
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
maxscale 26795 1 1 18:20 ? 00:00:00 /usr/bin/maxscale --user=maxscale
[root@localhost ~]#
restartすると落ちます!
なので、必要ならば「ExecStartPost」でプロセス起動の記述も書いてあげると良いだろう。この辺は運用時のコマンドによると思うので環境に合わせて。
●/usr/lib/systemd/system/maxscale.service
[Unit]
Description=MariaDB MaxScale Database Proxy
After=network.target
[Service]
Type=forking
Restart=on-failure
PIDFile=/var/run/maxscale/maxscale.pid
ExecStart=/usr/bin/maxscale --user=maxscale
ExecStartPost=/bin/sh -c 'systemctl start httpd'
ExecStopPost=/bin/sh -c 'systemctl stop httpd'
[Install]
WantedBy=multi-user.target
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
maxscale 27007 1 0 18:23 ? 00:00:00 /usr/bin/maxscale --user=maxscale
root 27009 1 1 18:23 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27013 27009 0 18:23 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27014 27009 0 18:23 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27015 27009 0 18:23 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27016 27009 0 18:23 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27017 27009 0 18:23 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
[root@localhost ~]#
[root@localhost ~]# systemctl stop maxscale
[root@localhost ~]#
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
[root@localhost ~]#
[root@localhost ~]# systemctl start maxscale
[root@localhost ~]#
[root@localhost ~]# ps -ef | grep -e [h]ttpd -e [m]axscale
maxscale 27067 1 0 18:24 ? 00:00:00 /usr/bin/maxscale --user=maxscale
root 27069 1 1 18:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27072 27069 0 18:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27073 27069 0 18:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27075 27069 0 18:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27076 27069 0 18:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 27077 27069 0 18:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
…まぁ、停止させたいのがアプリケーションサーバ用のプロセスだったりして、LBとかが手前にいるんだったらヘルスチェックで対処させた方が良さそうな気もするけど。