2

我的 ruby​​ 脚本创建了一个临时文件并产生了一个可能长时间运行的外部进程。无论脚本以何种方式终止,脚本结束后两者都不能继续存在。

我认为以下几行会解决问题:

stderr = File.open(Tempfile.new(__FILE__),'w')
trap("EXIT") { FileUtils.rm_f stderr.path }
pid = spawn("dd", *ARGV, STDERR => stderr )
trap("EXIT") { FileUtils.rm_f stderr.path; Process.kill pid }

他们应该是对以下 bash 代码的重写,这似乎工作正常,

dd_output=`mktemp`
trap "rm -f $dd_output" EXIT
dd "$@" 2>| $dd_output & pid=$!
trap "rm -f $dd_output; kill $pid" EXIT

但他们没有。如果稍后引发异常,则生成的进程不会死,否则会死。

谁能告诉我我做错了什么?

编辑:陷阱确实有效。上面的代码有多个瑕疵:

  1. Tempfile 自行处理——它很可能已经在陷阱处理程序中被删除,这可能会导致 FileUtils.rm_f 引发另一个错误,从而阻止。
  2. Process.kill 需要一个信号—— Process.kill “TERM”、pid(或“KILL”)。引发的错误掩盖了我错误调用 Process.kill 的错误。

固定代码:

 stderr = Tempfile.new(__FILE__)
 pid = spawn("dd", *ARGV, STDERR => stderr )
 trap("EXIT") { Process.kill "TERM", pid }

Ensure也可以。

4

1 回答 1

2

我认为确保在这里可以帮助您,它将始终执行里面的代码。它类似于 Java 的finally

stderr = Tempfile.new(__FILE__)

begin
  pid = spawn("dd", *ARGV, STDERR => stderr )
ensure
  FileUtils.rm_f stderr.path
  Process.kill pid
end

如果这不能解决问题,您可以尝试添加一个at_exit处理程序。

于 2015-03-02T23:18:01.207 回答