“Errno :: EMFILE:太多打开的文件”,创建本地图像

时间:2013-08-23 02:12:37

标签: ruby-on-rails rspec paperclip

在Rails中创建一个对象时,我想自动从资源目录中为它分配一个库存图像,以后可以被用户覆盖。

因此,我在创建对象时执行以下私有方法:

def save_stock_image
  image_path = Dir.glob(<list-of-images-from-directory>).sample

  File.open(image_path) do |file|
    self.image = file
    self.save!
  end
end

然而,经过6次RSpec测试后,我开始收到以下错误:

Failure/Error: let(:object) { create(:object) }
Errno::EMFILE:
  Too many open files - /tmp/16020130822-36578-q8j9v9.jpg
# ./app/models/object.rb:502:in `block in save_stock_image'
# ./app/models/object.rb:501:in `open'
# ./app/models/object.rb:501:in `save_stock_image'
# ./spec/controllers/object_controller_spec.rb:318:in `block (3 levels) in <top (required)>'
# ./spec/controllers/object_controller_spec.rb:344:in `block (4 levels) in <top (required)>'

上述错误在60次测试中约有40次。我已经看了几个SO问题,以及https://github.com/thoughtbot/paperclip/issues/1122https://github.com/thoughtbot/paperclip/issues/1000。我能找到的最接近的答案是确保文件描述符正在关闭。在我在块中使用File.open之前,我使用file.close明确关闭了文件 - 这也不起作用。

明显我做错了吗?有没有更好的方法来完成我想要做的事情?

更新

看起来它与Paperclip上传到S3之前创建的临时文件有关。关闭那些我错过的临时文件有什么东西吗?

3 个答案:

答案 0 :(得分:1)

我自己也碰到了这个。看起来主分支有一个修复。请在此处查看我的评论:

https://github.com/thoughtbot/paperclip/issues/1326?source=cc

答案 1 :(得分:0)

如果这是一个开发/测试环境,您需要快速解决。

尝试识别resque进程ID,终止它并重新启动resque服务器。

此外,您可以尝试以下

Redis.current.client.reconnect
$redis = Redis.current

答案 2 :(得分:0)

刚碰到这个,最新的代码对我没有帮助。因此,我通过生成子进程将关闭这些临时文件的工作委托给操作系统:

def save_stock_image
  ActiveRecord::Base.connection.disconnect!
  Proces.fork do 
    image_path = Dir.glob(<list-of-images-from-directory>).sample

    File.open(image_path) do |file|
      self.image = file
      self.save!
    end
  end
  Process.wait    
  ActiveRecord::Base.establish_connection
end

另外,请考虑在Process.wait上设置超时,如下所示:Waiting for Ruby child pid to exit