AWS
Ubuntu
EC2
unicorn
Linuxコマンド

unicorn を監視して、落ちたら自動再起動するワンライナー

今回は負荷の高いRailsアプリのunicornが落ちてしまうことがあり、

手動で再起動しているようでは、ダウンタイムが発生してしまうのでなんとか自動的に再起動をかけられないかと考えさがしていたところ、

手軽にできる方法を発見し、暫定的に採用させていただきました。

もっと良い方法や違うアプローチがあるかもしれませんが、

今回は表題の内容を紹介させていただきます。


環境


  • AWS EC2

  • Ubuntu

  • Rails

  • Unicorn

restart-server というunicornを再起動するコマンドを予め作成しておりましたので、

プロセスを監視してunicornがいなかったらそのスクリプトを実行するという形を取りました。

またデプロイ専用のユーザーで無いと、restart-serverは実行できないという環境です。


概要

linuxコマンドのwatchを利用して、60秒ごとにunicornと含まれるプロセスが存在するかを確認、

プロセス数が0であれば、restart-serverを実行するという具合です。

ただsshで接続してwatchを実行してもwatchを終了しなければ、sshを切断できませんので、

sshを繋ぎっぱなしにしなければなりません。

よってsshを切っても、watchが動き続けるようにnohuoを利用します。

それらを組み合わせてできたワンライナーが以下のものです。

nohup watch -n 60 "if [ 0 -eq `ps ax | grep unicorn | grep -v grep | wc -l` ] ; then restart-server ; fi" &


使用方法

{繰り返しの秒数}のところに繰り返し監視する感覚を秒数で入力します。0.1以下は設定不可

{実行するコマンド}のところに、unicornプロセスがなかったときに実行するコマンドを入力します。

{実行するコマンド}の部分はあまり長いもの入れられませんので、別途スクリプトを用意するなどして簡単に呼び出せるようにすることが必要です。

nohup watch -n {繰り返しの秒数} "if [ 0 -eq `ps ax | grep unicorn | grep -v grep | wc -l` ] ; then {実行するコマンド} ; fi" &

以下、各部分を簡単に解説していきます。

nohup <command> &

先頭のnohupと末尾の&nohupコマンドです。

その間に半角スペースを挟んで、ssh切断後も実行しておきたいコマンドを入れます。

今回はwatchコマンドです。

watch -n 60

この部分がwatchコマンドとオプション指定です。

-nが実行間隔を指定するオプションでその後に半角スペースにつづけて秒数を入力します。

if [ 0 -eq `ps ax | grep unicorn | grep -v grep | wc -l` ] ;

おなじみのif文です。[]内が条件式です。

0 -eq の部分がイコール0ならば真という条件式です。

続くps axが全てのプロセスを一覧表示するコマンド、|パイプで繋いでgrep unicornunicornを含むプロセスだけに絞り込みます。

ただこれだけだと、絞り込んだ結果の中にこのgrep自体もプロセスも含まれてしまいますので、grep -v grepgrepの実行プロセスを除外します。

最後のwc -lでその絞り込んだ結果を数字にします。

そうすることで0 -eqと数字で比較します。

unicornプロセスが居ないときは、プロセスリストにunicornと含まれるプロセスも0になりますので、

0と比較して真になれば、thenに続くコマンドが呼び出されるという形です。


注意点

当たり前のことかもですが、スペースに注意してください。

[];の前後のスペースが抜けるとうまくいきません。

あとクオートとバッククウォートにも注意が必要です。

if ~ fiまでがif文ですが、それをダブルクォーテーションでくくっています。

またps ~ -lまではバッククウォートでくくっています。


まとめ

こんなワンライナーで済ませてしまっていいものかとも思いますが、

きちんとしたunicorn監視&再起動の方法があればご教授ください。

自分でも引き続き調べていこうと思います。


参考にした記事

以下の記事を参考にさせていただきました。

非常に助かりました。ありがとうございました。

grepでこういう時はどうする?

SSHからログアウトした後もプロセスを起動しておく方法

シェルスクリプト(bash)の「 [ ] 」と「 [[ ]] 」の違い

grepでこういう時はどうする?