先日、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されて以下のようなプロセスツリーとなる。
1 2 3 4 5 6 7 8 9 10
| 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に停止させる。
1 2 3 4 5 6
| unicorn master (old) \_ unicorn master \_ unicorn worker[0] \_ unicorn worker[1] \_ unicorn worker[2] \_ unicorn worker[3]
|
- その後古いmasterプロセスに
KILL
シグナルを送信する。
1 2 3 4 5
| unicorn master \_ unicorn worker[0] \_ unicorn worker[1] \_ unicorn worker[2] \_ unicorn worker[3]
|
これでOK。
ただし、Unicornがデーモン化されていない場合はWINCH
シグナルがスルーされるので、いったん停止してから起動する。(後述のスクリプトではデーモン想定でも停止、起動の流れにしてしまっている。)
自動起動設定
上記を踏まえて自動起動の設定をする。
/etc/init.d/
に、例えば/etc/init.d/unicorn
ファイルを作成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| #!/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
|
上記スクリプトで reload
とした場合、Unicornのpreload_app
フラグがONになっている場合はアプリケーションの再ロードは行われないことに注意。アプリケーションの再ロードをしたい場合にはrestart
を指定する。
上記スクリプトをchkconfigで有効化し、適用されていることを確認。
1 2 3 4 5 6 7 8 9
| $ 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にご相談下さいませ!