railsマルチプロセスとログとlogrotate

先日パーティにお招きいただいたM社の方から、mongrel_clusterで複数プロセス立ち上げている時、logroateすると、ひとつのプロセスを残して、ログファイルを見失って正常に動作できなくなる、というご相談をいただきました。

美味しいお酒をいっぱいのませていただいたのでちょうど僕も使うアテがあるので、僕がよく使っているthinのケースを書いてみます。たぶんmongrelでもそんなに変わらないんじゃないかな〜。

マルチプロセスで起動する

・セッションをファイルじゃなくてDBに保存するようにする。やり方はググれば出てくるので省略。
・ログはproduction.logじゃなくてSTDERRに出力して、thinの方でファイルに書いてもらう。具体的には、config/environments/production.rbとかで

  config.logger = Logger.new(STDOUT)

という具合に。
・thinの設定

$ sudo ln -s /var/www/example/api/config/thin.conf /etc/thin/example.yaml
$ sudo emacs /var/www/example/api/config/thin.conf
---
chdir: /var/www/example/api
environment: production
servers: 3
address: 0.0.0.0
port: 3000
timeout: 30
log: log/thin_example.log
pid: tmp/pids/thin_example.pid
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
daemonize: true

これでlocalhost:3000,3001,3002と3プロセスが立ち上がります。
ログは、

$ ls -la api/log/
-rw-r--r--  1 root    root     3081 Aug  6 20:42 thin_example.3000.log
-rw-r--r--  1 root    root     1292 Aug  6 20:42 thin_example.3001.log
-rw-r--r--  1 root    root    15632 Aug  6 20:42 thin_example.3002.log

という具合にプロセスごとに別々に出力されます。

Rails3.2からログの行が他プロセスのものと混ざるようになった件について – 昼メシ物語 などを見ていると、一つのファイルにかいた時ログが混じるという話が出ているのですけど、そもそも複数プロセスから一個のファイルに書き込む時点で怖くて仕方ないので、
最初から分けてあったほうがいっそスッキリするんじゃないかな〜。

ログが複数にわかれていても、

tail -f log/thin_example.*.log

とすれば一つの窓で監視することができます。

ロードバランサー(apache)の設定

 こんなかんじで

$ sudo ln -s /var/www/example/api/config/httpd.conf /etc/httpd/conf.d/example.conf
$ emacs /var/www/example/api/config/httpd.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot "/var/www/example/html/"
ServerAdmin mogya+example@mogya.com
ErrorLog "/var/www/example/log/error_log"
TransferLog "/var/www/example/log/access_log"
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog /var/www/example/log/custom_log combined
ProxyPass /api/v2 balancer://example
ProxyPassReverse /api/v2 balancer://example
</VirtualHost>
<Proxy balancer://example>
BalancerMember http://localhost:3000
BalancerMember http://localhost:3001
BalancerMember http://localhost:3002
</Proxy>

いまどきapacheなんて・・・という方はherokuでもAWSでもお好きなフロントエンドでどうぞ。

logrotate

sudo ln -s /var/www/example/api/config/logrotate.conf /etc/logrotate.d/example
emacs /var/www/example/api/config/logrotate.conf
/var/www/example/api/log/* {
daily
missingok
rotate 1000
notifempty
copytruncate
create 0666 root root
sharedscripts
postrotate
/etc/init.d/thin restart > /dev/null
/etc/init.d/httpd restart > /dev/null
endscript
dateext
}

thinだけrestartだと直後の挙動が怪しかったので、httpdもrestartするようにしてあげたほうがいいみたいです。

$ sudo logrotate -dv /etc/logrotate.d/example

で文法チェック。

$ sudo logrotate -f /etc/logrotate.d/example

で動作確認を行うことができます。

環境

$ rails -v
Rails 3.2.13
$ thin -v
thin 1.5.1 codename Straight Razor
$ httpd -v
Server version: Apache/2.2.24 (Unix)
Server built:   May 20 2013 21:12:45