Rails日志转换是保持旧日志打开并填满它

时间:2011-10-04 14:15:49

标签: ruby-on-rails logging jrubyonrails

我帮助维护一个Rails网站。它在Solaris Sparc机器上运行JRuby 1.5.5,Rails 2.3.10。我遇到了与日志有关的问题。

为了阻止我们的日志文件变得过大并填满磁盘,我们正在使用内置于Logger类的日志转换。在config / environments / production.rb中,我们有:

config.logger = Logger.new(config.log_path, 10, 100.megabyte)

当日志文件达到100兆字节时应该旋转日志文件,并且只保留10个文件。

问题是双重的:Rails没有正确地旋转日志,并且它保持打开旧的日志文件以写入它 - 但它写的只是一些请求的重复内容。所以,如果我ls -l log,我会看到类似的事情:

-rw-r--r-- 83040892 Oct  4 15:07 production.log
-rw-r--r-- 3303158664 Oct  4 15:07 production.log.0
-rw-r--r-- 104857616 Oct  2 23:13 production.log.1
-rw-r--r-- 104857618 Oct  1 17:12 production.log.2

注意最近循环的日志如何仍然打开并仍在写入(运行pfiles确认Rails服务器仍然有三个日志文件句柄)。另请注意,它在两天内达到了3千兆字节,通常我们每天可以达到100千兆字节。这是因为它充满了重复的请求。我不能轻易地将它粘贴在这里,但是日志充满了10月3日18:50(相信是日志旋转点)的相同1000行请求,一遍又一遍地打印。根据过去的经验,日志文件将继续填充这些重复的内容,直到磁盘填满。

日志转换/ Rails日志记录是否破损? (我们的日志文件用法并不奇怪:我们不做任何直接日志记录,它只是来自Rails框架。)明显的下一步是尝试像logrotate,但如果Rails拒绝关闭旧的日志文件和我永远在给他们写垃圾,我怀疑它不会解决我的问题(因为日志永远不会被关闭,因此磁盘空间永远不会恢复)。

4 个答案:

答案 0 :(得分:10)

症状似乎是一个旧日志文件仍在继续使用,尽管您已成功轮换日志。

原因很可能一个或多个Rails实例或线程仍在使用旧文件句柄

解决方案是为了确保所有Rails实例在日志轮换后完全重启,因此它们都使用新文件句柄/名称。

使用logrotate 而不是config.logger来旋转日志!

我建议使用UNIX logrotate来轮换日志,而不是使用config.logger。 恕我直言,这是一个更好的解决方案,更可靠,您可以更好地控制日志轮换,并且您可以提供一些后轮换命令来重新启动Rails进程。 (通过logrotate的postrotateendscript选项)

见:

http://www.opencsw.org/packages/logrotate/(适用于Solaris的logrotate包)

http://www.thegeekstuff.com/2010/07/logrotate-examples/(带示例的logrotate教程)

http://linux.die.net/man/8/logrotate

你能使用Unicorn吗? - Unicorn内置支持通过USR1信号重新打开应用程序中的所有日志文件 - 这允许logrotate以原子方式旋转文件... - Unicorn跟踪并重新启动它的工作人员!您可以在日志轮换后终止工作,Unicorn将重新启动它们,确保它们使用新的日志文件。

参见:https://github.com/blog/517-unicorn(Unicorn优于Mongrel的许多优点)

如果您使用的是Mongrel ,则无法切换到Unicorn:

使用logrotate,并通过postrotate选项重新启动Mongrels。

希望这会有所帮助..

答案 1 :(得分:2)

在处理Rails日志文件时,我总是使用平台的日志轮换机制。遵循http://www.nullislove.com/2007/09/10/rotating-rails-log-files/的建议,因为我也从http://overstimulate.com/articles/logrotate-rails-passenger运行Passenger。

第一种方法使用logrotate copytruncate方法创建新的日志文件,因此仍然具有句柄的进程将始终写入当前日志文件。

在服务器上检查的其他事项包括:

  • 确保没有任何宝石或插件在ruby上下文中具有Logger的句柄。
  • 由于您正在使用JRuby,因此确保在某个地方没有卡住/失控的线程,而该线程试图满足请求但是卡住了日志。
  • 就像使用Passenger一样,请考虑不时地重新启动Rails服务器进程。我知道这实际上是一个黑客,但它可能会有效。

答案 2 :(得分:2)

尼尔,

我不知道这是否适用于您的特定情况,但我遇到了类似的问题,我想我只是解决了它。就我而言,我有两个症状。第一个是和你一样的问题 - 我的日志轮换很麻烦......特别是,production.log.1文件保持打开状态,并且生产日志也正在登录时正在进行记录。第二个症状是日志文件所有权和组成员身份将不断更改为root。 My Rails应用程序是通过Capistrano部署的,使用'部署者'用户,因此每当应用程序尝试写入不再由部署者拥有的日志文件时,我都会收到各种各样的错误。

我很尴尬地说我花了多长时间才意识到这两个问题的原因是什么。在某个地方,我用应用程序的crontab 作为root 更新了cron。这一定是在我在命令提示符处搞乱时...如果我刚刚通过Capistrano保留了我的部署配方,我就不会无意中这样做了。在任何情况下,我终于查看了/ var / spool / cron / crontabs,我发现了我的crontab文件的两个副本...一个用于部署者,一个用于root用户。因此,cron为我的应用程序启动的进程正在重复 - 一个在部署程序下运行,另一个在根目录下运行。这是第二个搞砸了。一旦我删除了root的crontab,一切都会更好。

一些警告:在我的设置中,root的crontab中没有与应用程序无关的任务,即它与deployer的crontab完全相同...所以删除它对我没有任何副作用。此外,我的服务器正在运行Ubuntu ...你的crontabs的路径可能会有所不同。

希望有所帮助。

  • 大卫

答案 3 :(得分:0)

我想你忘记了's',以兆字节为单位 或者改为使用类似的东西

config.logger = Logger.new(config.log_path, 10, 102400)

同时查看此链接非常有帮助

http://railsillustrated.com/logger-tricks.html