Ruby守护进程导致ActiveRecord日志记录IOError。

5

我目前正在使用Ruby编写一个项目,其中使用了ActiveRecord gem进行数据库交互,并且我正在尝试使用以下代码记录所有的数据库活动,使用ActiveRecord::Base.logger属性:

ActiveRecord::Base.logger = Logger.new(File.open('logs/database.log', 'a'))

这对于迁移等工作很好用(由于禁用日志会导致NilClass错误,因此似乎需要启用日志记录),但是当我尝试运行包含调用ActiveRecord对象的线程守护进程的项目时,脚本会出现以下错误

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/logger.rb:504:in `write': closed stream (IOError)

非常感谢您对这个问题的关注。目前我已经开始查看其他代码,以寻找在更加线程安全的情况下实现 ActiveRecord 日志记录的方法。如果您有任何好的想法,请不吝赐教。再次感谢!
谢谢,
Patrick
3个回答

4

延时任务(delayed_job)使用守护进程(daemons)和活动记录(activerecord),在进行守护化之前,获取打开的文件,然后在守护化后重新打开。

@files_to_reopen = []
ObjectSpace.each_object(File) do |file|
  @files_to_reopen << file unless file.closed?
end

Daemons.run_proc("xxxxx_name",:dir=>pid_file,:dir_mode=>:normal) do
  Dir.chdir(Rails.root)
  # Re-open file handles
  @files_to_reopen.each do |file|
    begin
      file.reopen file.path
      file.sync = true
    rescue ::Exception
    end
  end
end

不要忘记添加写入权限。file.reopen file.path, "a" - Yaro

4
我遇到了同样的问题。你需要先将进程守护化,然后再加载Rails环境。

你能解释一下你所说的“daemonize and then load Rails env”是什么意思吗? - Chris Kimpton
Daemons.run_proc('your_daemon', daemon_options) { require File.expand_path(File.join(File.dirname(FILE), '..', 'config', 'environment')) # do stuff } - Logan Koester
请注意,在守护进程后尝试获取__FILE__信息是行不通的,因为进程会失去这些信息。您需要在守护进程之前保存该路径。 - Kelvin

2

原来,迁移需要使用ActiveRecord::Base.logger变量,不能为nil,这解释了问题的前半部分。但是,当使用文件而不是STDERR时,我仍然无法解决IOError。


问题是否源于同步?您可以尝试使用Rails的BufferedLogger,看看是否可以解决这个问题? - François Beausoleil
我们最终使用DRB编写了一个简单的日志记录应用程序,它处理了所有线程的错误。 - Patrick O'Doherty
我使用 Rails.logger = ActiveRecord::Base.logger = Logger.new(STDOUT) 进行修复。 - Pioz

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