Unicornの自動起動設定
先日、OS起動時にUnicornが自動起動するよう設定する機会があり、その際にUnicornの停止や再起動についておさらいした覚え書きである。
前提
Unicornの停止方法
公式ドキュメントに記載されているが、要約する。
Unicornには停止用コマンドなどは用意されていない。Unicornはひとつのmasterプロセスと複数のworkerプロセスからなるが、masterプロセスにシグナルを送信することで停止できる。
送信シグナルによって以下の違いがある。
- QUIT:gracefulな終了(workerの処理待ちをする。)
- INT/TERM:強制終了(強制的にworkerプロセスをkillする。)
※一般的に、killコマンドでシグナル指定しなければTERMが送信され、Ctrl+Cでプロセスを止めればINTが送信されるが、INT/TERMのいずれでも停止処理は同じである。
http://bogomips.org/unicorn.git/tree/lib/unicorn/http_server.rb 参照。
なお、上記ソースは通常Unicornユーザは読む必要はないが、Unicornがどう動くかを勉強するのにはよい、とソース自体に書いてあった。
Unicornの再起動方法
Unicornは無停止再起動が可能であり、masterプロセスにHUP
シグナルを送信すれば再起動するが、 preload_app
フラグがONの場合にはアプリケーションの再ロードが走らないことに注意。ただし、
preload_app
フラグがONでもアプリケーションの再ロードをしたい場合には以下のようにする。
- masterプロセスに
USR2
シグナルを送信→新しいmaster, workerプロセスがforkされて以下のようなプロセスツリーとなる。
unicorn master (old)
\_ unicorn worker[0]
\_ unicorn worker[1]
\_ unicorn worker[2]
\_ unicorn worker[3]
\_ unicorn master
\_ unicorn worker[0]
\_ unicorn worker[1]
\_ unicorn worker[2]
\_ unicorn worker[3]
- 古いmasterプロセスに
WINCH
シグナルを送信し、古いworkerプロセスをgracefulに停止させる。
unicorn master (old)
\_ unicorn master
\_ unicorn worker[0]
\_ unicorn worker[1]
\_ unicorn worker[2]
\_ unicorn worker[3]
- その後古いmasterプロセスに
KILL
シグナルを送信する。
unicorn master
\_ unicorn worker[0]
\_ unicorn worker[1]
\_ unicorn worker[2]
\_ unicorn worker[3]
これでOK。
ただし、Unicornがデーモン化されていない場合はWINCH
シグナルがスルーされるので、いったん停止してから起動する。(後述のスクリプトではデーモン想定でも停止、起動の流れにしてしまっている。)
自動起動設定
上記を踏まえて自動起動の設定をする。
/etc/init.d/
に、例えば/etc/init.d/unicorn
ファイルを作成。
#!/bin/sh
#chkconfig:2345 85 70
#description:unicorn shell
NAME="Unicorn"
ENV=production
ROOT_DIR="/opt/rails/some_app/current"
GEMFILE="${ROOT_DIR}/Gemfile"
PID="${ROOT_DIR}/tmp/pids/unicorn.pid"
CONF="${ROOT_DIR}/config/unicorn.rb"
OPTIONS=""
start()
{
if [ -e $PID ]; then
echo "$NAME already started"
exit 1
fi
echo "start $NAME"
cd $ROOT_DIR
su - ec2-user -c "cd ${ROOT_RIR} && BUNDLE_GEMFILE=${GEMFILE} bundle exec unicorn -c ${CONF} -E ${ENV} -D ${OPTIONS}"
}
stop()
{
if [ ! -e $PID ]; then
echo "$NAME not started"
exit 1
fi
echo "stop $NAME"
kill -QUIT `cat ${PID}`
}
force_stop()
{
if [ ! -e $PID ]; then
echo "$NAME not started"
exit 1
fi
echo "stop $NAME"
kill -INT `cat ${PID}`
}
reload()
{
if [ ! -e $PID ]; then
echo "$NAME not started"
start
exit 0
fi
echo "reload $NAME"
kill -HUP `cat ${PID}`
}
restart()
{
stop
sleep 3
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
force-stop)
force_stop
;;
reload)
reload
;;
restart)
restart
;;
*)
echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
;;
esac
- 上記スクリプトは http://tkoyama1988.hatenablog.com/entry/2014/09/15/175038 からほぼ流用させていただいた。
- 上記スクリプトはAmazon Linux AMI release 2014.09で動作確認済み。
- ランレベルはNginxと同様、停止起動順序はよろしく設定してください。
- 各種ファイルパスもよろしく設定してください。
上記スクリプトで reload
とした場合、Unicornのpreload_app
フラグがONになっている場合はアプリケーションの再ロードは行われないことに注意。アプリケーションの再ロードをしたい場合にはrestart
を指定する。
上記スクリプトをchkconfigで有効化し、適用されていることを確認。
$ sudo chkconfig unicorn on
$ chkconfig --list
acpid 0:off 1:off 2:on 3:on 4:on 5:on 6:off
atd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
...途中略
sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
td-agent 0:off 1:off 2:on 3:on 4:on 5:on 6:off
udev-post 0:off 1:on 2:on 3:on 4:on 5:on 6:off
unicorn 0:off 1:off 2:on 3:on 4:on 5:on 6:off
あとは、実際に検証して動くことをご確認ください。
Ruby on Railsを活用したWebサービスや業務システム開発をご検討の企業様は、是非MMMにご相談下さいませ!