[英]Rails paperclip upload images folder - Errno::EMFILE
首先,我想为我的英语不好道歉。
我有一段代码,使用gem PaperClip 3.3.1上传到文件服务器文件夹。 在我尝试上传包含50张照片的文件夹之前,每件事最多能显示哪几张照片(最多30张)。 然后我得到以下错误信息:
Errno::EMFILE (Too many open files - identify -format %m '/tmp/4209520130906-10816-1kk0w0o.jpg[0]'):
我在系统中检查ulimit -a,在我的环境中,我可以同时打开1200个文件。 因此,我感到十分震惊:
watch -n1 'lsof -a -p <rails server pid> | wc -l'
并且随着每次迭代,打开文件的数量在增加
110 - starting count
160 - after first iteration (number from folder)
240 - second iteration
320
376
457
...
1118 - of about 32 iteration
crash ~ :)
我发现问题是由proc引起的,该proc将image_path添加到数据库中,并在需要特殊格式时调整其大小(在html输入解析期间)
因此,在调试器我拼命地跑下commad检查什么文件红宝石成立。
ObjectSpace.each_object(File){ |f| puts f.path }
我发现有50个文件上传了名称,其中包括“ RackMultipart”,并且经过迭代后,tmp文件夹中的文件数被新文件添加了新名称(可能是回形针临时文件)。 我以为peperclip或某些应用程序代码不会关闭文件,因此在proc结尾时我添加了以下代码:
now = Time.now.to_formatted_s( :number )[0..7]
ObjectSpace.each_object(File).map do |f|
if f.path.include?( "/tmp/" ) && !f.closed?
unless f.path.include? "RackMultipart#{now}"
f.close
f = nil
end
end
end
之后,什么都没有发生。 在调试器中我运行命令
ObjectSpace.each_object(File){ |f| puts ( f.closed? '+' : '-' ) }
并且打开的文件数(-)是正确的(〜160),但是命令仍然列出了关闭的文件。 我关上门后它们不应该消失吗?
截断的方法看起来像下面这样:
def function(g, files)
...
asset = proc do |img|
...
file = files.find{|f| f.original_filename == src}
if file
geo = Paperclip::Geometry.from_file file.path
if(geo.width <= 20 && geo.height <= 20)
...
else
asset = figure.assets.build
asset.file = file ## HERE RUNS
...
end
now = Time.now.to_formatted_s( :number )[0..7]
ObjectSpace.each_object(File).map do |f|
if f.path.include?( "/tmp/" ) && !f.closed?
unless f.path.include? "RackMultipart#{now}"
f.close
f = nil
end
end
end
else
...
end
end
...
while img = g.find_first(".//img")
asset.call(img) # !HERE HAPPENS
img.remove!
end
end # end function
资产模型定义:
class Asset < ActiveRecord::Base
...
has_attached_file :file, url: "/system/:class/:attachment/:id/:style_:filename",
styles: lambda { |attachment| attachment.instance.switch_styles },
:convert_options => {medium: lambda{|asset| asset.is_table? ? "-units PixelsPerInch -resample 120 -strip" : "-strip"},
all: '-strip'}
validates_attachment :file, content_type: { content_type: ["image/jpg","image/png","image/gif","image/jpeg","image/tiff"] },
size: { in: 0..10.megabytes }
def is_table?
...
end
def switch_styles
self.file.content_type == "image/tiff" ?
{ backup: "100%", original: ["100%", :png], medium: [self.is_table? ? "" : "800x600>", :png], small: ["300x300>", :png], formula: ['50%', :png] } :
{ medium: self.is_table? ? "" : "800x600>", small: "300x300>", formula: '50%' }
end
end
我希望你能理解我写的内容;)
在此先感谢您4的帮助。
好。 这段代码没有错,一切正常。 但是有时有人在父级父类中禁用了GarbageColector。 可能会加快解析过程。 因此,现在当文件数量超过ulimit的70%时,我会打开GC,如果它清理了不必要的临时文件,我会再次将其关闭。
编辑:函数运行,然后再次禁用GC
def gc_check
if ObjectSpace.each_object(File).to_a.size > 850
GC.start if GC.enable
else
GC.disable
end
end
希望对您有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.