我正在使用 ruby 标准记录器,我想要每天轮换一次,所以在我的代码中我有:
Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')
它运行良好,但它创建了两个文件errors.log.20130217
和errors.log.20130217.1
.
我怎样才能强制它每天只创建一个文件?
我正在使用 ruby 标准记录器,我想要每天轮换一次,所以在我的代码中我有:
Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')
它运行良好,但它创建了两个文件errors.log.20130217
和errors.log.20130217.1
.
我怎样才能强制它每天只创建一个文件?
您的代码对于长时间运行的应用程序是正确的。
发生的事情是您在某一天不止一次运行代码。
第一次运行它时,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 将是您最好的选择恕我直言。