【问题标题】:Is there any way to make a Ruby temporary file permanent?有什么方法可以使 Ruby 临时文件永久化?
【发布时间】:2014-02-12 15:47:25
【问题描述】:

如果我通过Tempfile 创建了一个临时文件,除了将其复制到另一个文件之外,还有什么方法可以使其“永久”吗?当关联的Tempfile 实例被垃圾收集或进程终止时,我想避免它被删除。

在相关点上,有没有办法利用Tempfile 机制(或使用类似机制)来获取“新”文件名,而无需创建该名称的文件?

【问题讨论】:

  • 您必须在该上下文中定义永久,因为根据定义,位于 RAM 上的任何东西都是注意永久。所以要么你必须使用文件(数据库、txt、XML 等)或内存。我能想到的两者之间没有办法(技术上存在,见cold boot attacks,但这是一个副作用)。但是,出于好奇,如果 RAM 或文件系统都不足以处理,您想要完成什么?
  • 明确一点:你的意思是你还想要一个临时文件,在进程成功退出时最终被释放?
  • @atmosx “永久”是指“文件系统中不会在垃圾回收或退出时被删除的文件”。 FWIW,我对 Ruby Tempfile 机制的理解是,它实际上是在文件系统中创建文件,而不仅仅是在内存中,而且关于它们的唯一“临时”是它们会被自动删除。事实上,我已经能够从这些 Tempfile 对象之一(例如,在调试器中)获取路径名,并在另一个终端窗口中通过 shell 命令将其作为文件访问。
  • @p11y 不,我希望临时文件不再是临时文件(即不删除)。
  • @atmosx 像我的大多数 SO 问题一样,我对答案的兴趣超出了特定问题或用例,但在这种特定情况下,我在我的应用程序中使用了许多临时文件,有时在调试或开发,我想在程序退出后轻松“保留”一些用于分析。

标签: ruby temporary-files


【解决方案1】:

不是真的。对于问题本身,请参见:

ObjectSpace.undefine_finalizer(tmpfile)

Tempfile 库使用 Ruby ObjectSpace 终结器在垃圾回收时自动删除自身。通过使用上面的行,如果您不删除它,您可以删除 Tempfile 自行删除的能力。所以,例如:

$ irb
2.0.0p0 :001 > require "tempfile"
 => true 
2.0.0p0 :002 > t = Tempfile.new("test")
 => #<Tempfile:/tmp/test20140122-6655-80p4b7> 
2.0.0p0 :003 > t.write("Hi!")
 => 3 
2.0.0p0 :004 > ObjectSpace.undefine_finalizer(t)
 => #<Tempfile:/tmp/test20140122-6655-80p4b7> 
2.0.0p0 :005 > exit
$ cat /tmp/test20140122-6655-80p4b7
Hi!
$ 

不过,还有一些事情需要注意。 Tempfile 将使用系统临时文件目录,如/tmp,操作系统会每隔一段时间自动清理一次(例如on every boot)。因此,即使您“持久化”该文件,您也需要接受它消失,或者将其移动到默认情况下不会被清除的目录,例如/var/tmp(用于持久临时的 Linux 目录文件)。


至于你的第二个问题,试试这个来自here的代码:

Dir::Tmpname.create('your_application_prefix') { |path| puts path }

它需要require "tmpdir"

【讨论】:

  • @PeterAlfvin:很高兴他们提供了帮助。
  • 最好的解决方案是不要将 TempFile 用于需要永久保存的文件,并明确地创建/删除它们。 TempFile 适用于真正临时且可以轻松重新创建的文件。
  • @theTinMan 最适合谁?请参阅我对以“就像我的大多数 SO 问题......”开头的问题的评论。
  • 最适合那些使用 TempFile 创建文件然后想在事后保留它的人。相反,设置一个使用普通 File 类的调试标志,这样你就有了持久性,然后,当没有设置该标志时,使用 TempFile。这样你就不必弄乱课堂本身了。至少你可以使用$DEBUG,它是在命令行上将-d 传递给Ruby 时设置的。
  • 除了我不知道我正在创建的数百或数千个临时文件中的 哪个 文件之外,我需要稍后进行分析,直到出现一些运行时条件.换句话说,我在创建时知道我以后是否需要它。
【解决方案2】:

我认为最简单的解决方案可能是猴子修补Tmpfile 类以添加persist 方法。此方法采用临时文件将被移动到的文件名。此外,它还移除了终结器,这样临时文件就不会在退出时被删除。

require 'tempfile'
require 'fileutils'

class Tempfile
  def persist(filename)
    FileUtils.mv(self.path, filename)
    ObjectSpace.undefine_finalizer(self)
  end
end

file = Tempfile.new('tmp')
file.write('hello world')
file.close
file.persist('hello.txt')

运行此程序将通过移动原始临时文件而不是复制它来创建一个持久文件./hello.txt

【讨论】:

  • 你不能只复制文件而不弄乱终结器,我想知道吗?
  • @SergioTulentsev 这也是我最初的想法,但问题明确是关于“除了复制”的一种方式。
猜你喜欢
  • 1970-01-01
  • 2017-09-24
  • 1970-01-01
  • 2019-08-08
  • 2013-10-05
  • 2021-11-19
  • 2011-07-17
  • 2017-08-04
  • 1970-01-01
相关资源
最近更新 更多