在ruby中捕获Ctrl-c

Tim*_*ite 102 ruby copy-paste exception

我通过了一个长期运行的遗留ruby程序,它有很多次出现

begin
  #dosomething
rescue Exception => e
  #halt the exception's progress
end
Run Code Online (Sandbox Code Playgroud)

贯穿始终.

如果不追踪每一个可能的异常,每个异常都可以处理(至少不是立即),我仍然希望能够有时关闭它CtrlC.

我想以一种只添加代码的方式这样做(所以我不会影响现有的行为,或者在运行过程中错过一个被捕获的异常.)

[ CtrlC是SIGINT,或SystemExit,它似乎与SignalException.new("INT")Ruby的异常处理系统相同.class SignalException < Exception,这就是为什么会出现这个问题的原因.

我想写的代码是:

begin
  #dosomething
rescue SignalException => e
  raise e
rescue Exception => e
  #halt the exception's progress
end
Run Code Online (Sandbox Code Playgroud)

编辑:此代码有效,只要您获得要捕获正确的异常类.这是SystemExit,Interrupt或IRB :: Abort,如下所示.

Way*_*rad 126

问题是当Ruby程序结束时,它会通过引发SystemExit来实现.当一个control-C进来时,它会引发中断.由于SystemExitInterrupt都是从Exception派生的,因此您的异常处理是在其轨道中停止退出或中断.这是修复:

无论你在哪里,都要改变

rescue Exception => e
  # ...
end
Run Code Online (Sandbox Code Playgroud)

rescue StandardError => e
  # ...
end
Run Code Online (Sandbox Code Playgroud)

对于那些无法更改为StandardError的人,请重新引发异常:

rescue Exception => e
  # ...
  raise
end
Run Code Online (Sandbox Code Playgroud)

或者,至少重新提升SystemExit和Interrupt

rescue SystemExit, Interrupt
  raise
rescue Exception => e
  #...
end
Run Code Online (Sandbox Code Playgroud)

您所做的任何自定义异常都应该来自StandardError,而不是Exception.

  • @Tim,找到 irb.rb(在我的系统上,它在 /usr/lib/ruby/1.8/irb.rb 中)并找到主循环(搜索 @context.evaluate)。看看救援条款,我想你就会明白为什么 IRB 会这样行事。 (2认同)

Log*_*ldo 71

如果你可以包装整个程序,你可以执行以下操作:

 trap("SIGINT") { throw :ctrl_c }

 catch :ctrl_c do
 begin
    sleep(10)
 rescue Exception
    puts "Not printed"
 end
 end
Run Code Online (Sandbox Code Playgroud)

这基本上CtrlC使用了catch/throw而不是异常处理,所以除非现有的代码已经有了catch:ctrl_c,否则应该没问题.

或者你可以做一个trap("SIGINT") { exit! }.exit!立即退出,它不会引发异常,因此代码不会意外地捕获它.

  • 请注意,IRB中的Ctrl-C发送IRB :: Abort,而不是SIGINT.否则@ Logan的答案是一个解决方案. (2认同)

Eri*_*tch 37

如果你无法将整个应用程序包装在一个begin ... rescue块中(例如,Thor),你可以陷阱SIGINT:

trap "SIGINT" do
  puts "Exiting"
  exit 130
end
Run Code Online (Sandbox Code Playgroud)

130是标准退出代码.


nro*_*ose 5

我正在使用ensure,效果很好!这是为了当你的东西结束时你想要发生的事情,不管它为什么结束。