在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进来时,会引发中断 。 由于SystemExit和Interrupt都是从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
很好的效果! 无论事情何时结束,这就是你想要发生的事情。