在ruby中捕获Ctrl-C

我通过了一个长期运行的遗留ruby程序,其中有无数的事件

begin #dosomething rescue Exception => e #halt the exception's progress end 

贯穿始终。

没有追踪每一个可能的exception,这些都可以处理(至less不是立即),我仍然希望能够按Ctrl Cclosures它。

我想这样做只会增加代码(所以我不会影响现有的行为,或者在运行过程中错过捕获的exception)。

[ Ctrl C是SIGINT或SystemExit,它似乎等同于Rubyexception处理系统中的SignalException.new("INT")class SignalException < Exception ,这就是出现这个问题的原因。]

我想写的代码是:

 begin #dosomething rescue SignalException => e raise e rescue Exception => e #halt the exception's progress end 

编辑:这个代码工作,只要你得到你想要陷阱的exception的类正确。 这可以是SystemExit,Interrupt或IRB :: Abort,如下所示。

问题是,当Ruby程序结束时,通过引发SystemExit来完成 。 当一个控制-C进来时,会引发中断 。 由于SystemExitInterrupt都是从exception派生的,所以你的exception处理就是停止它的踪迹中的退出或中断。 这是修复:

无论你在哪里,都可以改变

 rescue Exception => e # ... end 

 rescue StandardError => e # ... end 

对于那些不能更改为StandardError的人,请重新提出exception:

 rescue Exception => e # ... raise end 

或者至less重新升级SystemExit和Interrupt

 rescue SystemExit, Interrupt raise rescue Exception => e #... end 

你所做的任何自定义exception应该来自StandardError ,而不是Exception

如果你可以包装你的整个程序,你可以做如下的事情:

  trap("SIGINT") { throw :ctrl_c } catch :ctrl_c do begin sleep(10) rescue Exception puts "Not printed" end end 

这基本上是Ctrl C使用catch / throw而不是exception处理,所以除非现有的代码已经有了一个catch:ctrl_c,它应该没问题。

或者你可以做一个trap("SIGINT") { exit! } trap("SIGINT") { exit! }exit! 立即退出,它不会引发exception,所以代码不会意外地捕捉到它。

如果你不能把你的整个应用程序封装在一个begin ... rescue块(例如Thor)中,你可以捕获SIGINT

 trap "SIGINT" do puts "Exiting" exit 130 end 

130是一个标准的退出码。

我正在使用ensure很好的效果! 无论事情何时结束,这就是你想要发生的事情。