【问题标题】:Cleaning up after a ruby script -- trapping signalsruby 脚本后清理——捕获信号
【发布时间】:2015-05-03 10:33:43
【问题描述】:

我的 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 也可以。

【问题讨论】:

    标签: ruby bash error-handling signals bash-trap


    【解决方案1】:

    我认为 ensure 在这里也许能帮到你,它总是会执行里面的代码。类似于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 处理程序。

    【讨论】:

    • at_exit 可能是在这里尝试的第一件事。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多