我得到的错误:在Ruby中写了很多文件后打开的文件太多了

我有一个脚本,生成像16000的HTML页面,并将其保存在系统中。 1013页后,我得到的错误:打开的文件太多。

这是生成文件的Ruby代码

FileUtils.mkdir_p "public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}" FileUtils.mkdir_p "public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}/#{n/1000}" html_file = File.new("public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}/#{n/1000}/#{n}.html", "w") html_file.write(html) html_file.close 

你可以看到我closures文件的最后一行….

有人知道我在这里做错了吗? 我有Ubuntu 8.04.4 LTS

非常感谢

编辑:

这是整个脚本

  def self.fetching_directory_page(n=1, letter = nil) id = letter == '' ? "" : "/#{letter.upcase}" url = "this is a valid url :)" agent = WWW::Mechanize.new page = agent.get(url) html = page.search('div#my_profile_body').to_html prefix = id == '' ? 'all' : letter FileUtils.mkdir_p "public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}" FileUtils.mkdir_p "public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}/#{n/1000}" html_file = File.new("public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}/#{n/1000}/#{n}.html", "w") html_file.write(html) html_file.close puts "+ CREATED #{prefix}/#{n/1000}/#{n}.html" new_url = page.parser.xpath("//a[@class='next_page']")[0]['href'] rescue nil if new_url.present? self.fetching_directory_page(n+1, letter) end end 

它将获取我的用户目录的所有用户并保存页面以进行caching。 它总共产生16000个文件。

这是ulimit-a的结果

  core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 24640 max locked memory (kbytes, -l) 32 max memory size (kbytes, -m) unlimited open files (-n) 24000 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 24640 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 

编辑/ etc / security / limits后,我没有得到错误Too many open files但它只是卡住了

lsof -u username返回一个或多或less600个条目的列表,并且在执行脚本时不会改变

我不确定这是否是解决您问题的最佳方法,但可能有所帮助:

尝试评论一半的代码。 如果问题仍然存在,那么请留下余下的一半。 继续这样做,直到问题消失。 一旦问题消失,尝试取消注释一些代码。 继续这样做,直到问题返回。 更可能的是,你刚刚注销的行与错误有关。 这种解决问题的方法有时被称为“二元砍”。

在这种情况下,您可能需要确保无论是否调用fetching_directory_page都不会每次打开新文件而不关闭它。

打开文件不会导致问题。 这是递归的方法。 我改变了,事情很好。

问题似乎是在操作系统,而不是在Ruby脚本本身。

尝试从以前的SO问题这个建议:

检查当前用户有多少文件有权打开:在终端运行ulimit -a并检查打开的文件(-n) 。 默认值是1024。

要解决这个问题,你必须修改以下文件: /etc/security/limits.conf

这是一个小问题,但Ruby支持在File.open使用一个块,该块将自动关闭打开的文件。 在Ruby中使用这种形式被认为是习惯用法,而不是你如何使用这种形式:

 html_file = File.new("public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}/#{n/1000}/#{n}.html", "w") html_file.write(html) html_file.close 

应该:

 File.open("public/users_directory/#{DEFAULT_COUNTRY_CODE}/#{prefix}/#{n/1000}/#{n}.html", "w") do |html_file| html_file.print html end 

IO.open 文档继承File.open:

没有关联块,IO.open是:: new的同义词。 如果给出了可选的代码块,它将作为参数传递给io,当块终止时,IO对象将自动关闭。 在这种情况下,:: open返回块的值。