我正在使用ruby标准记录器,我想每天轮换一次,所以在我的代码中我有:
Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')
它运行正常,但它创建了两个文件errors.log.20130217
和errors.log.20130217.1
。
如何强制它每天只创建一个文件?
答案 0 :(得分: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
没有解决方案(AFAIK)使用Ruby记录器及其内置旋转器来同时管理由多个应用程序(即工作人员,进程,线程)编写的日志。这是因为每个应用程序都有自己的日志文件句柄。
或者,使用任何良好的日志旋转工具,例如Tin Man用户在问题评论中建议的logrotate:http://linuxcommand.org/man_pages/logrotate8.html
一般来说,logrotate将是你最好的选择恕我直言。