轻松备份长期运行的ruby进程

时间:2009-04-07 07:32:56

标签: ruby

我打算运行可能需要一个月才能完成的红宝石流程。如果可能的话,我想确保停电或按错按钮不会花费我整个月的工作。

是否有一种简单的方法可以定期将程序的状态保存到磁盘? (涉及更多工作的技术包括添加代码,这些代码可以整理数据库之外的所有内容,或者可能使用虚拟机来处理进程的操作系统)

(对于那些感兴趣的人:该过程涉及解析一个知名网站的一个数GB的XML文件,处理一些信息,并将信息保存到ActiveRecord数据库中。两次。)

编辑:项目为this one,XML文件为pages-articles.xml(例如enwiki-20090306-pages-articles.xml)。没有什么专有的,我只是不想进入“Plz halp”模式。第一遍得到维基百科页面标题列表,下一遍确定从每个页面到另一个页面的第一个链接,然后我计算一些统计数据。

正如一些回答者所建议的那样,从我离开的地方继续,可能是一个有效的选择。如果它在第一次传递期间崩溃,那么我可能会重新运行它,告诉它不要添加已经存在的条目。如果它在第二次传递期间崩溃,那么我应该只要求它为尚未计算其链接的页面构建链接。如果在计算统计数据期间崩溃,我可以重新计算统计数据。

其他编辑Save a process’ memory for later use?询问此问题的更一般版本。看起来你无法轻易备份长时间运行的进程。

5 个答案:

答案 0 :(得分:1)

我想不出一个超级简单的方法来做到这一点,但是如果你愿意稍微修改你的代码,你可能会从YAML(一个易于使用的标记库)获得一些帮助。 yaml.org)。导入YAML库为每个对象提供一个.to_yml函数,该函数将序列化整个对象,因此可以将其保存到文件中,也可以从yml中恢复对象。 因此,这需要添加一些代码来定期保存,但实际的保存位可能相对容易。此外,yaml是内置的,因此无需下载。

require "yaml"
def backup(objects_im_Using)
  out_file = File.open("prefix"+Time.now.strftime('%Y-%M-%d')+".yml","w")
  objects_im_Using.each {|object| out_file 

(虽然我认为真正的ruby方法是让备份函数产生一个块或者某些东西。)

对不起,没有比这更好的方法了。我有兴趣阅读更好的回答这个问题!

答案 1 :(得分:1)

从上周末我的工作机器意外断电(建筑物其他地方的建筑)的角度来看,我同情这个想法。

分区任务有什么价值吗?输入文件可以重新编写成许多较小的文件吗?

我知道,这个数量级更小,但我每天早上都会在一些AR模型上加载大约200万行。为了解决我遭遇的令人震惊的数据库延迟问题(不同国家的数据库服务器 - 请不要问)我将输入的CSV文件重写为16个“片段”。每个片段都记录在Fragment模型中,这有助于我识别重新运行的任何完成失败。它运行得非常好,并且在需要时重新启动很简单。通常的运行时间约为30分钟。

如果您的XML输入结构合理,那么将子结构(我确信有一个比这更好的术语)提取到单独的文件中应该相当简单。我不知道SAX解析器能够以多快的速度执行此操作 - 可能不是太可怕,但如果它仍然太慢,它可以在没有XML库的情况下完成。考虑向目标模型添加一列以识别它从中加载的片段 - 这样就可以很容易地删除不完整的运行。

除此之外,考虑将所有状态保存在一个类中并使用Marshal定期保存?

答案 2 :(得分:1)

随着它的进行,它会保存到数据库中,但是从您的问题来看,您似乎无法单独从那里停止使用该数据。

内存中的数据是否可以保存在临时表或临时列中,这样可以让您从上次停止的地方继续操作?也许您不需要整个状态 - 也许数据的一个子集可以让您重新创建电源关闭的点(或其他)。

答案 3 :(得分:0)

行。现在我们知道了一点,我认为整个问题可能没有实际意义。我猜想,从一个善良的星期五愚弄,你应该能够在几个小时内提取你需要的数据。

您可能需要几天时间才能完成自己的设置,弄清楚您需要存储的内容,如何存储它以及在获得它之后如何处理它,但这是有趣的部分反正。

以下是我认为您可以解决问题的方法。

您知道文件结构。它是一个庞大的(令人难以置信的大,让我们诚实)XML文件;我看到大约21GB。在结构上它很简单。您需要<page>元素,您需要从中提取一些基本信息:标题,文本(或至少其中的链接)和id。这是一个非常简单的解析工作 - 不需要XML库或诸如此类的东西,简单的字符串匹配算法就足够了。对于标题,使用String #index查找打开和关闭标记并在其间提取位。对于文本中的第一个链接,它有点棘手,因为您必须根据规则确定第一个真实链接。

将21GB的文本读入内存将是一个很好的技巧,但当然你不必这样做:你只需要一个有用大小的块来处理。一兆字节似乎是合理的。或者10K。这不是什么大不了的事 - 砍掉GB左右来试验。

我有一个脚本,每分钟提取和写入一个大约250,000个标题/第一链接对的文本文件。它忽略了“重定向”页面(因此它处理了更多的页面)并忽略了带有“:”的链接(到目前为止还不够聪明,但我想在那里放一些处理)。没有regexen,哎呀,没有要求。大约30行不是很简洁的代码。它发现了大约523万个标题(我认为有更多不需要的标题:文件,项目等等),并在大约20分钟内编写了一个更集中和可管理的1.03GB输出(见下文)。 Ruby(MRI)1.8.6,Windows Vista,2GHz Core 2 Duo。他们说Ruby很慢。

前3行:

Anarchism, [[political philosophy]]
Autism, [[Neurodevelopmental disorder|brain development disorder]]
Albedo, [[Sun]]

答案 4 :(得分:0)

Save a process’ memory for later use?询问此问题的更一般版本。看起来你无法轻易备份长时间运行的进程。