使用 rails 执行大型脚本

Posted

技术标签:

【中文标题】使用 rails 执行大型脚本【英文标题】:Execute big scripts with rails 【发布时间】:2011-12-22 03:32:36 【问题描述】:

我制作了一个非常大的脚本来感受我的初始数据到我的 Rails 应用程序中。我的 CSV 文件中有大约 3000 行和 10000 张图片。

大概上传了 300 次后,我收到了这条消息:

/usr/local/lib/ruby/gems/1.9.1/gems/activesupport-3.0.9/lib/active_support/core_ext/kernel/agnostics.rb:7:in ``': Cannot allocate memory - identify -format %wx%h '/tmp/stream20111104-14788-1hsumv7.jpg[0]' (Errno::ENOMEM)

我的上传脚本:

if (row[28] != nil)
   hotelalbum = HotelAlbumPhoto.find_or_create_by_title(h.title)
   hotelalbum.description = "Album photo de l'hotel " + h.title.capitalize
   hotelalbum.hotel_id = h.id
   hotelalbum.save

   files =  Dir.glob('IMAGES/' + row[28].gsub(/\\/,'/') + '/*.jpg')
   i =0
   for file in files
      i += 1
      photopath = File.expand_path('../../import', __FILE__) + '/' + file
      photoname = file.split('/').last
      if (i==1)
        hotelalbum.thumbnail = open(photopath)
        hotelalbum.save
      end
      if (i==1)
        h.thumbnail = open(photopath)
      end
      photo = HotelImage.find_or_create_by_image_file_name_and_hotel_album_photo_id(photoname,hotelalbum.id)
      if (photo.image_file_size == nil || photo.image_file_name != photoname)
          photo.image = open(photopath)
          photo.activated = true
          photo.alt = "Photo de l'hotel " + h.title
          photo.save
      else
         puts photopath + ' already updated'
      end
   end
end

当我使用 top 命令检查内存时,我看到 ruby​​ 进程在每次上传时使用更多内存。我该如何管理?

感谢您的帮助

ps:我的服务器是一个512Mb内存的虚拟机,一个解决方案是增加这个内存,但我希望找到另一个。

【问题讨论】:

你在使用paperclip这样的附件管理器吗? 作为另一个诊断点,如果你禁用了图像组件,它是否还有内存问题? 【参考方案1】:

我不知道open函数是在哪里定义的,但是我怀疑我没有看到对应的close...

更新更好的主意,将 photo.image = open(photopath) 更改为 photo.image = File.read(photopath)

根据文档,阅读:

Opens the file, optionally seeks to the given offset, then 
returns length bytes (defaulting to the rest of the file). 
read ensures the file is closed before returning.

【讨论】:

好像没必要关闭……不过你说得对,很奇怪。 如果不关闭,则文件句柄可能与文件内容一起保留在内存中... 你知道如何关闭吗?谢谢 我什至不知道你在叫什么 open。通常它在一个类上,例如 File.open 之类的。你的 open 函数是在哪里定义的? 我不知道,我只是在我的脚本中调用 open。它应该是rails的默认打开功能:)【参考方案2】:

看起来像 ImageMagick 的内存泄漏问题?也许这将有助于使用in_groups_of 处理大块或块中的列表,并在每个块之后使用GC.start 强制垃圾收集:

files.in_groups_of(100) |chunk| 
   # process chunk
   GC.start

【讨论】:

以上是关于使用 rails 执行大型脚本的主要内容,如果未能解决你的问题,请参考以下文章

rails,使用咖啡脚本出现语法错误

如何在 Delphi 中执行包含许多 GO 语句的大型 SQL 脚本? [关闭]

用其他gems rails调用ruby脚本

如何通过Rails控制台在Digital Ocean上写入权限来执行Ruby脚本?

如何在 Rails 项目中运行日常任务/脚本?

有没有办法在大型机上使用 python 脚本发送 ISPF 命令并获取作业统计信息?