Ruby 中如何实现日志轮转(Log Rotation)?
Ruby 日志轮转:Logger.new 支持按天/周/月轮转('daily'/'weekly'/'monthly')或按大小轮转(保留个数, 大小)。本文介绍内置方案和 logrotate 配合。
Ruby 的 Logger 内置轮转功能:Logger.new('app.log', 'daily') 按天轮转,Logger.new('app.log', 10, 100.megabytes) 按大小轮转(保留 10 个文件,每个最大 100MB)。
按时间轮转
require 'logger'
# 每天轮转
logger = Logger.new('application.log', 'daily')
# 每周轮转
logger = Logger.new('application.log', 'weekly')
# 每月轮转
logger = Logger.new('application.log', 'monthly')
logger.info("这条日志会被自动轮转")
按大小轮转
require 'logger'
# 保留 10 个日志文件,每个最大 100MB
logger = Logger.new('application.log', 10, 100 * 1024 * 1024)
logger.info("日志到达大小上限时自动轮转")
自定义格式
logger = Logger.new('application.log', 'daily')
logger.formatter = proc do |severity, datetime, progname, msg|
"#{datetime.strftime('%Y-%m-%d %H:%M:%S')} [#{severity}] #{msg}\n"
end
logger.level = Logger::INFO
外部工具:logrotate
也可以不在应用层做轮转,交给系统的 logrotate:
# /etc/logrotate.d/myapp
/var/log/myapp/application.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
}
copytruncate 让应用不用重新打开文件句柄。
使用观测云 DataKit 文件采集时,按实际文件路径配置采集规则,轮转前后各写一条带唯一编号的日志,核对是否连续到达。再测试采集器重启后的结果;本地与远端保留期应覆盖故障恢复和追溯需求。
常见问题(FAQ)
Q:按时间轮转后旧文件会自动删除吗?
A:不会。按时间轮转只是创建新文件,需要配合 logrotate 或定期脚本清理旧文件。按大小轮转会自动删除最旧的文件。
Q:多进程写同一个日志文件安全吗?
A:Logger 的轮转在多进程环境下可能出问题(两个进程同时轮转)。建议用 logrotate 的 copytruncate 方案,或让每个进程写独立文件。
Q:Rails 项目怎么做日志轮转?
A:Rails 的 config/environments/production.rb 中配置 config.logger = Logger.new('log/production.log', 'daily'),或让 logrotate 处理。