如何最佳地为Rails应用程序轮转日志

16

我有一个来自Slicehost的1GB切片,并且在该服务器上运行了4个项目。所有4个应用程序都是Ruby on Rails应用程序。我想知道确保日志文件轮换的最佳方法是什么。

我希望有4个不同的日志文件,每个应用程序对应一个,而不是一个包含所有4个应用程序日志的大日志文件。

我正在运行Ubuntu操作系统。

我正在运行Passenger。


可能是 Ruby on Rails 生产日志旋转 的重复问题。 - tirdadc
7个回答

17

我也使用logrotate(您需要通过apt-get安装)。在您的/etc/logrotate.d/目录中创建一个新的logrotate文件。这是我的其中一个示例:

# for the rails logs
/home/apps/*/shared/log/*log {
  daily
  rotate 14
  notifempty
  missingok
  compress
  sharedscripts
  postrotate
    /usr/bin/touch /home/apps/application1/current/tmp/restart.txt
    /usr/bin/touch /home/apps/application2/current/tmp/restart.txt
  endscript
}
# for the apache logs
/home/apps/logs/*log {
  daily
  rotate 14
  notifempty
  missingok
  compress
  sharedscripts
  postrotate
    /etc/init.d/apache2 restart
  endscript
}

这会旋转Rails的production.log日志和Apache的访问/错误日志(我在Passenger下运行我的应用程序)。


感谢提供示例,我认为这很有帮助。不过,为什么您在旋转日志后要重新启动应用程序呢? - Luke Francl
1
如果您不重新启动应用程序(或Apache),则日志将不再追加,这可能会导致问题。我可能是错的,但我知道这曾经是一个问题。 - Bill Turner
1
如果您添加copytruncate选项,它将把prod.log复制到prod.log.0,然后截断prod.log,保留文件描述符,您无需重新启动应用程序。尽管copytruncate选项可能会在旋转文件时丢失一些日志数据。 - Kamilski81
1
我发布了一个解决方案(https://dev59.com/-HI-5IYBdhLWcg3w99kH#22615644),它不需要重新启动应用程序。为了进行日志轮换而重新启动会对性能造成不必要的影响,因此最好尽可能避免这种情况。 - Shyam Habarakada

6
我会建议您使用Rails Logger提供的内置旋转功能:

我会建议您使用Rails Logger提供的内置旋转功能:

# in config/application.rb
config.logger = Logger.new(Rails.root.join('log', "#{Rails.env}.log"), 3, 10.megabytes)

当日志文件达到10MB时,这将会轮替日志文件并保存最近的3个轮替日志。


2
使用Logger而不是默认的BufferedLogger唯一的问题,正如我吃过的亏一样,就是如果您在应用服务器(Passenger、Unicorn等)中使用多个进程/线程,则消息将交错。 - Duke
嗯,我一直在使用多个进程向带有旋转参数的普通记录器写入单个消息,并对Passenger进行了大量负载测试,但没有看到任何交错。现在我会注意这个问题。 - Gabe Kopley
虽然我没有看到消息被分段和交错的情况,但在系统负载下,我发现日志在达到10M之前就被轮换了,并且整个消息顺序错乱。 - Gabe Kopley
在使用 .megabytes 方法之前,我需要添加 require 'active_support/core_ext/numeric/bytes'。 - Eduardo
@GabeKopley,以上回答已经过去几年了。我想知道您是否仍在使用这种方法,今天是否存在任何问题? - Christian Fazzini

5
我们最近也遇到了这个问题,发现logrotate并不是最好的解决方案。使用它需要每次日志轮换时重新启动rails应用程序,这似乎会影响性能,是不必要的。更好的解决方案是在应用程序配置文件中覆盖默认的Rails日志记录器。
# in config/environments/development.rb
config.logger = Logger.new("#{Rails.env}.log", "daily")

然后使用一个脚本清理 n 天前的文件。如果您喜欢,可以使用 logrotate 完成这部分工作。我们使用以下 rake 任务:

desc "Cleanup application logs older than 30 days"
task :logs => :environment do
  require 'fileutils'
  Dir.glob("#{Rails.root}/log/*.log.*").
    select{|f| File.mtime(f) < (Time.now - (60*60*24*30)) }. # older than 30 days
    each { |f| 
      puts "Removing #{f}"
      FileUtils.rm f 
    }
end

6
logrotatecopytruncate 选项允许原始日志文件进行原地截断,从而确保在旋转日志时 Rails 服务器可以继续写入日志。因此,在进行日志轮换时无需重启 Rails。 - Prakash Murthy
apachectl graceful 会产生明显的性能影响吗? - timurb
@Shyam Habarakada,只是确认一下,你用于清理旧日志的脚本是放在lib/tasks文件夹中吗? - ltdev

3
这是元编程,它是否应该在ServerFault或SO上进行讨论还有争议。 logrotate是许多操作系统的标准包,如果您还没有安装,可以使用apt-get install logrotate命令进行安装。您可以强制它按照您想要的计划旋转任何日志,并使用不同的策略(如每个文件“gzip 7天然后删除”)。
请调查/etc/logrotate.d

2
就我个人而言,这似乎是一个非常合理的程序员话题。我倾向于认为SO是为程序员而不仅仅是编程而设立的。 - John Munsch
不过你的想法似乎与常见问题解答相悖。但是我已经注意到了。 - Jed Smith

2

以下是我的Capistrano安装步骤。我将其复制到部署文件中,并在创建应用程序的服务器环境或日志轮换配置更改时运行它。

namespace :setup do
  task :install_logrotation, :roles => :app do
    logrotate = <<-BASH 
      #{shared_path}/log/*.log {
        daily
        missingok
        rotate 30
        compress
        size 5M
        delaycompress
        sharedscripts
        postrotate
          #{signal_unicorn("USR1")}
        endscript
      }
    BASH
    tmpfile = "/tmp/#{application}.logrotate"

    put(logrotate, tmpfile)
    run "#{sudo} chown root:root #{tmpfile} && #{sudo} mv -f #{tmpfile} /etc/logrotate.d/#{application}"
  end
end
signal_unicorn会执行"#{sudo} kill -s #{signal} cat #{unicorn_pid}"命令。USR1信号会告诉它重新加载所有文件,因此它将附加到新的日志文件中。
祝玩得开心!

0

如上所述,为了避免需要重新启动应用程序,您可以使用以下完整的logrotate配置:

/etc/logrotate.d/rails

<path_to_rails_app>/log/*.log {
  daily
  size 100M
  missingok
  notifempty
  rotate 4
  compress
  delaycompress
  copytruncate
  nodateext
 }

0

ActiveSupport::Logger 是根据 Rails General Configuration 的默认记录器。

这将为每个512兆字节轮换日志文件,并保留最新的50个文件。

config.logger = ActiveSupport::Logger.new(Rails.root.join('log', "#{Rails.env}.log"), 50, 512 * 1024 * 1024)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接