在ruby中捕获Ctrl-c
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在ruby中捕获Ctrl-c相关的知识,希望对你有一定的参考价值。
我通过了一个长期运行的遗留ruby程序,它有很多次出现
begin
#dosomething
rescue Exception => e
#halt the exception's progress
end
贯穿始终。
如果没有追踪每一个可能的异常,这些异常都可以处理(至少不是立即),我仍然希望能够使用CtrlC有时关闭它。
我想以一种只添加代码的方式这样做(所以我不会影响现有的行为,或者在运行过程中错过一个被捕获的异常。)
[CtrlC是SIGINT,或SystemExit,它似乎等同于Ruby的异常处理系统中的SignalException.new("INT")
。 class SignalException < Exception
,这就是为什么会出现这个问题的原因。
我想写的代码是:
begin
#dosomething
rescue SignalException => e
raise e
rescue Exception => e
#halt the exception's progress
end
编辑:此代码有效,只要您获得要捕获正确的异常类。这是SystemExit,Interrupt或IRB :: Abort,如下所示。
问题是当Ruby程序结束时,它会通过引发SystemExit来实现。当一个control-C进来时,它会引发中断。由于SystemExit和Interrupt都是从Exception派生的,因此您的异常处理是在其轨道中停止退出或中断。这是修复:
无论你在哪里,都要改变
rescue Exception => e
# ...
end
至
rescue StandardError => e
# ...
end
对于那些无法更改为StandardError的人,请重新引发异常:
rescue Exception => e
# ...
raise
end
或者,至少重新提升SystemExit和Interrupt
rescue SystemExit, Interrupt
raise
rescue Exception => e
#...
end
您所做的任何自定义异常都应该来自StandardError,而不是Exception。
如果你可以包装整个程序,你可以执行以下操作:
trap("SIGINT") { throw :ctrl_c }
catch :ctrl_c do
begin
sleep(10)
rescue Exception
puts "Not printed"
end
end
这基本上有CtrlC使用catch / throw而不是异常处理,所以除非现有的代码已经有一个catch:ctrl_c,它应该没问题。
或者你可以做一个trap("SIGINT") { exit! }
。 exit!
立即退出,它不会引发异常,因此代码不会意外地捕获它。
如果你不能将你的整个应用程序包装在begin ... rescue
块(例如,Thor)中,你可以捕获SIGINT
:
trap "SIGINT" do
puts "Exiting"
exit 130
end
130是标准退出代码。
我正在使用ensure
效果很好!这是你希望在你的东西结束时发生的事情,无论它为什么结束。
在Ruby中使用ZeroMQ方式干净地处理Ctrl-C:
#!/usr/bin/env ruby
# Shows how to handle Ctrl-C
require 'ffi-rzmq'
context = ZMQ::Context.new(1)
socket = context.socket(ZMQ::REP)
socket.bind("tcp://*:5558")
trap("INT") { puts "Shutting down."; socket.close; context.terminate; exit}
puts "Starting up"
while true do
message = socket.recv_string
puts "Message: #{message.inspect}"
socket.send_string("Message received")
end
以上是关于在ruby中捕获Ctrl-c的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 控制台应用程序中捕获 ctrl-c (SIGINT)
Ruby 命令行:如何通过命令行中的文本发送 CTRL-C 命令?