Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 为什么Pathname.rmtree在Signal.trap(';EXIT';)上失败_Ruby_Signals_Fileutils_Pathname - Fatal编程技术网

Ruby 为什么Pathname.rmtree在Signal.trap(';EXIT';)上失败

Ruby 为什么Pathname.rmtree在Signal.trap(';EXIT';)上失败,ruby,signals,fileutils,pathname,Ruby,Signals,Fileutils,Pathname,我正在尝试创建一个临时目录,该目录在脚本退出时被删除 #/usr/bin/env ruby 需要“路径名” 需要“tmpdir” Tmp_dir=Pathname.new(dir.mktmpdir) 信号陷阱('退出'){ Tmp_dir.rmtree 把“做清理” } puts“将在此消息后退出” Doing cleanup消息永远不会触发,目录保持完整。经过一些测试,似乎Tmp_dir.rmtree从未运行过,也没有任何后续操作 建议Pathname.rmtree调用FileUtils.r

我正在尝试创建一个临时目录,该目录在脚本退出时被删除

#/usr/bin/env ruby
需要“路径名”
需要“tmpdir”
Tmp_dir=Pathname.new(dir.mktmpdir)
信号陷阱('退出'){
Tmp_dir.rmtree
把“做清理”
}
puts“将在此消息后退出”
Doing cleanup
消息永远不会触发,目录保持完整。经过一些测试,似乎
Tmp_dir.rmtree
从未运行过,也没有任何后续操作

建议
Pathname.rmtree
调用
FileUtils.rm\u r
,因此我尝试这样做:

#/usr/bin/env ruby
需要“fileutils”
需要“路径名”
需要“tmpdir”
Tmp_dir=Pathname.new(dir.mktmpdir)
信号陷阱('退出'){
FileUtils.rm_r(Tmp_dir.to_路径)
把“做清理”
}
puts“将在此消息后退出”
它是有效的。那么为什么
rmtree
版本的信号陷阱与内核的At\u出口处理程序不同呢 你在评论中说你不想使用,但实际上并不是一个确切的同义词。实际上,这两种方法的行为明显不同。您可以很容易地看到这一点,如下所示:

# prints nil because variable not in scope; can't raise exceptions
Signal.trap(0) { p defined?(dir); p dir; raise dir }; dir="foo"; exit

# instance variables accessible; won't raise when undefined
Signal.trap(0) { p defined?(@dir); p @dir }; exit

# raises NameError because variable not in scope
at_exit { p defined?(dir); p dir }; dir="foo"; exit

# instance variable in scope, but won't raise when undefined
at_exit { p defined?(@dir); p @dir }; exit

# instance variable in scope; can raise manually
at_exit { p defined?(@dir); p @dir; raise @dir }; exit
如果您想知道它们为什么不同,您可能需要检查解析器或当前Ruby引擎的底层实现。这可能是一个bug,也可能是Ruby核心团队的故意选择。无论哪种方式,它们在Ruby 2.7.1中都有不同的行为

在At_出口处理程序中使用实例变量 正如所演示的,使用带有捕获信号的局部变量会带来范围界定问题,并且所需代码的其他实现可能不可靠,也不符合您的用例。您应该通过注册处理程序,并将临时目录名存储在实例或类变量中

当@dir被定义为顶级作用域中的实例变量或处理程序的已注册实例变量时,通过注册处理程序将实现您对irb或命令行的期望。路径名不是严格必需的,但包含在其中以匹配当前代码

require 'pathname'
require 'tmpdir'

at_exit { @dir.rmtree }

@dir = Pathname.new Dir.mktmpdir
p @dir
使用块进行自动清理 通过使用命令的块形式,可以完全避免信号/退出处理程序中的作用域问题。例如:

require 'tmpdir'

Dir.mktmpdir do |dir|
  # do something with dir
end

这将在块退出时清理临时目录,而不必注册退出处理程序或信号陷阱。根据我的经验,这通常比延迟闭包更容易测试和调试,但您的里程数肯定会有所不同。

如果这是一个范围问题,
FileUtils
解决方案可能不起作用,但它确实起作用。如果我在退出时使用
而不是
Signal.trap
(并且不更改代码中的任何其他内容),它也可以工作,但这并不能解释为什么
Signal.trap
不能工作,以及为什么
rmtree
之后的每个命令都不能运行。块形式不适合我的用例。此外,我想了解代码失败的原因,而不仅仅是解决问题。