使用Ruby标准Logger每天只创建一个日志

Eki*_*bal 5 ruby logging ruby-on-rails

我正在使用ruby标准记录器,我想每天轮换一次,所以在我的代码中我有:

Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')  
Run Code Online (Sandbox Code Playgroud)

它工作得很好,但它创建了两个文件errors.log.20130217errors.log.20130217.1.

我如何强制它每天只创建一个文件?

joe*_*son 11

您的代码适用于长时间运行的应用程序.

发生的事情是你在某一天不止一次运行代码.

第一次运行它时,Ruby会创建一个日志文件"errors.log".

当日期更改时,Ruby会将文件重命名为"errors.log.20130217".

但不知何故,你再次运行代码,也许你正在运行使用类似代码的两个应用程序(或进程,工作者或线程),并且你的记录器看到文件名"errors.log.20130217"已经存在.

您的记录器不想破坏该文件,但仍需要将"errors.log"重命名为日期,因此记录器创建了另一个文件名"errors.log.20130217.1"

要解决此问题,请仅运行一次代码.

如果您正在运行名为"foo"和"bar"的多个应用程序,则使用"foo-errors.log"和"bar-errors.log"等日志文件名.或者,如果您使用多个工作人员,请为每个工作人员提供自己的日志文件名(例如,使用工作人员的进程ID或工作池数组索引,或者您是否跟踪工作人员).

如果你真的想用Ruby记录器解决这个问题,你需要覆盖记录器#shift_log_period,这样就不会选择".1"后缀.您可以将Logger子类化并编写您已磨损的#shift_log_period以检测该日期是否存在现有日志文件,如果是,则使用它而不是执行文件重命名.

这是从记录器中导致它的代码:

def shift_log_period(period_end)
  postfix = period_end.strftime("%Y%m%d") # YYYYMMDD
  age_file = "#{@filename}.#{postfix}"
  if FileTest.exist?(age_file)
    # try to avoid filename crash caused by Timestamp change.
    idx = 0
    # .99 can be overridden; avoid too much file search with 'loop do'
    while idx < 100
      idx += 1
      age_file = "#{@filename}.#{postfix}.#{idx}"
      break unless FileTest.exist?(age_file)
    end
  end
  @dev.close rescue nil
  File.rename("#{@filename}", age_file)
  @dev = create_logfile(@filename)
  return true
Run Code Online (Sandbox Code Playgroud)

没有解决方案(AFAIK)使用Ruby记录器及其内置旋转器来同时管理由多个应用程序(也称为工作者,进程,线程)编写的日志.这是因为每个应用程序都有自己的日志文件句柄.

或者,使用任何良好的日志旋转工具,例如Tin Man用户在问题评论中建议的logrotate:http://linuxcommand.org/man_pages/logrotate8.html

一般来说,logrotate将是你最好的赌注恕我直言.