部署 rails 生产环境下的日志问题

kamechen · 2011年12月25日 · 最后由 hiveer 回复于 2014年06月03日 · 9455 次阅读

在生产环境多个 THIN 进程下,用日志切分的方式会存在问题

config.logger = Logger.new("#{Rails.root}/log/#{Rails.env}.log", 10, 10.megabytes)

深入到 Logger 类去看了下,这种方式好像有问题,一个进程对日志切分了以后,其他进程写入的日志就会乱了。 比如开了两个 THIN,THIN1 和 THIN2,这两个进程初始化的时候都是对 production.log 写入日志,当 THIN1 写入日志的时候到达设定的大小时,就会先关闭,然后将 production.log 重命名为 production.log.0,然后新建 production.log 文件并重新开启日志,但这时 THIN2 引用的还是原来的日志文件,即重名后的 production.log.0 文件,当 THIN2 处理请求写入日志时,发现日志到达指定大小了,也会和 THIN1 一样,首先将 production.log.0 重命名为 production.log.1,然后将 production.log 重命名为 production.log.0(这时 production.log 并未到达指定大小就被增长了),同时也新建 production.log 文件并重新开启日志,这时 THIN1 引用的是被重命名后的 production.log.0 且未到达指定大小,而 THIN2 引用的是 production.log,两个进程写入的日志就乱了!

这是 Logger 切分日志的主要方法:

def shift_log_age
  (@shift_age-3).downto(0) do |i|
    if FileTest.exist?("#{@filename}.#{i}")
      File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
    end
  end
  @dev.close
  File.rename("#{@filename}", "#{@filename}.0")
  @dev = create_logfile(@filename)
  return true
end

不知道大家有没有发现过这个问题???

Race condition? 如果不用Logger内建的 rotate,而是用 Linux 自己的 logrotate 呢?通常我都是按天来切分日志,很少按照尺寸来切,我觉得这样便于日志分析。 http://linuxers.org/howto/howto-use-logrotate-manage-log-files

我一直感觉 Rails 的 Logger 太弱,以前一直喜欢 Java 的 Log4j。你可以试下 Ruby 的 log4r https://github.com/colbygk/log4r

#1 楼 @lgn21st 恩,是的,发现 logrotate 非常好,那就不需用自带的日志切分了,谢谢!

#2 楼 @camel 开始是用 Log4r,后来发现在多进程的情况下,也存在日志切分问题,会被覆盖;才换了 RUBY 本身的日志,后来又发现 RUBY 本身的在进程下也有问题,呵呵!还是 Logrotate 比较好!

#2 楼 @camel 很过的 gem 他们并不支持 log4r,所以我倾向于还是用 Rails 的 Logger

需要 登录 后方可回复, 如果你还没有账号请 注册新账号