systemdとは
Systemdとは、Linuxの起動処理やシステム管理を行う仕組みです。CentOS7以前は /etc/init.d
以下にシェルスクリプトを置いてOS起動時にサービスの自動起動を行っていましたが、CentOS7からはsystemdは *.service
ファイルを記述しUnitという単位で管理するようになりました。
この仕組を利用すればサービスの自動起動だけでなく、プロセスの監視を行い停止したら再起動を行うこともできます。
delayed_jobとは
古くからRailsで利用されているバックグラウンド処理を行うための仕組みです。delayed_job_active_record.gem
を利用します。
delayed_jobの問題点
delayed_jobはDBにバックグラウンド処理を行うためのキュー情報を保存するため、RDBMSの再起動等で接続が切断してしまうと、サービス自体が停止してしまいます。そのため、以前は monit 等を利用してプロセスを監視し、停止している場合は再起動を行う必要がありました。
ここでは、systemdを利用してプロセスの監視を行ってみます。
delayed_job起動スクリプト
/opt/project/bin
以下にdelayed_jobの起動スクリプトを置きます。 project の部分はご自分の環境に合わせて書き換えて下さい。
delayed_job.sh
Capistrano
のdelayed_jobプラグインが実行するコマンドを真似て次のように記述しました。パス等はご自分の環境に合わせて書き換えて下さい。
#! /bin/sh
sudo su -l kazuhisa -c "cd /home/kazuhisa/apps/project/current && RAILS_ENV=production /home/kazuhisa/.rbenv/bin/rbenv exec bundle exec bin/delayed_job -n 1 start"
実行権限を与えます。
# chmod 755 delayed_job.sh
serviceファイル
/etc/systemd/system
以下にserviceファイルを置きます。
delayed_job.service
注意点は次の通り
-
ConditionPathExists
に起動スクリプトを置いたパスを設定します。 -
ExecStart
に起動スクリプトをフルパスで設定します。 - Restartは
on-failure
を指定します。よくalways
を指定している例があるのですがCapistranoでデプロイ時にdelayed_jobがリスタートしたタイミングで、死活監視が動作してしまい、無駄に再起動が実行されてしまいます。on-failure
を指定することで異常終了したときだけサービスを再起動することができます。 -
RestartSec
はプロセスの停止を検知してから起動するまでの時間を秒で指定します。 -
PIDFile
はdelayed_job実行時のpidファイルの場所を設定します。
[Unit]
Description = start delayed_job
After=local-fs.target
ConditionPathExists=/opt/project/bin
[Service]
ExecStart=/opt/project/bin/delayed_job.sh
Restart=on-failure
RestartSec=30
Type=forking
User=kazuhisa
Group=kazuhisa
PIDFile=/home/kazuhisa/apps/project/current/tmp/pids/delayed_job.pid
[Install]
WantedBy=multi-user.target
サービスの有効化
# systemctl daemon-reload
# systemctl enable delayed_job.service
# systemctl start delayed_job.service
delayed_jobの再起動の確認
プロセスを強制的に停止してみます。しばらく待つと再起動することが確認できると思います。
$ cat tmp/pids/delayed_job.pid
17449
$ kill -9 17449
(しばらく待つ)
$ cat tmp/pids/delayed_job.pid
20409
$ ps ax | grep 20409
20409 ? Sl 0:00 delayed_job
20419 pts/1 S+ 0:00 grep --color=auto 20409
これで安心してdelayed_jobを使うことができますね。