【问题标题】:"Errno::EMFILE: Too many open files" with local images on create“Errno::EMFILE:打开的文件太多”,创建时带有本地图像
【发布时间】:2013-08-23 02:12:37
【问题描述】:

在 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 之前创建的临时文件有关。关闭那些我丢失的临时文件有什么问题吗?

【问题讨论】:

    标签: ruby-on-rails rspec paperclip


    【解决方案1】:

    我自己也遇到了。看起来主分支有一个修复。在这里查看我的 cmets:

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

    【讨论】:

      【解决方案2】:

      如果这是一个开发/测试环境并且您想要快速解决问题。

      尝试识别 resque 进程 id,将其杀死并重新启动 resque 服务器。

      另外你可以试试下面的

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

      【讨论】:

        【解决方案3】:

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

        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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-14
          • 2019-08-11
          • 2018-04-01
          • 1970-01-01
          • 2012-02-16
          相关资源
          最近更新 更多