Answers:
TL; DR:StandardError改为用于常规异常捕获。重新引发原始异常时(例如,在救援时仅记录异常),救援Exception可能就可以了。
Exception是根Ruby的异常层次结构,所以当你rescue Exception从拯救一切,包括子类,如SyntaxError,LoadError和Interrupt。
救援Interrupt可以防止用户CTRLC用来退出程序。
抢救会SignalException阻止程序正确响应信号。除以外,它将是不可杀死的kill -9。
抢救SyntaxError意味着eval失败的s会默默地这样做。
所有这些都可以通过运行这个程序,并试图显示CTRLC或者kill它:
loop do
  begin
    sleep 1
    eval "djsakru3924r9eiuorwju3498 += 5u84fior8u8t4ruyf8ihiure"
  rescue Exception
    puts "I refuse to fail or be stopped!"
  end
end
救援Exception甚至不是默认设置。在做
begin
  # iceberg!
rescue
  # lifeboats
end
不从中营救,从中Exception营救StandardError。通常,您应该指定比default更为具体的内容StandardError,但是从中进行救援可以Exception 扩大范围而不是缩小范围,并且可能导致灾难性的结果,并且使错误查找变得极为困难。
如果您确实想从中解脱,StandardError并且需要一个例外的变量,则可以使用以下形式:
begin
  # iceberg!
rescue => e
  # lifeboats
end
等效于:
begin
  # iceberg!
rescue StandardError => e
  # lifeboats
end
从Exception日志记录/报告目的中可以挽救过来的几种常见情况之一,在这种情况下,您应该立即重新引发异常:
begin
  # iceberg?
rescue Exception => e
  # do some logging
  raise # not enough lifeboats ;)
end
ThrowableJava一样
                    ADAPTER_ERRORS = [::ActiveRecord::StatementInvalid, PGError, Mysql::Error,                             Mysql2::Error, ::ActiveRecord::JDBCError, SQLite3::Exception]然后rescue *ADAPTER_ERRORS => e
                    在真正的规则是:不要扔掉异常。您的报价作者的客观性值得怀疑,事实证明是这样的事实:
不然我会刺你
当然,请注意,信号(默认情况下)会引发异常,并且通常长时间运行的进程会通过信号终止,因此捕获Exception而不终止信号异常将使您的程序很难停止。所以不要这样做:
#! /usr/bin/ruby
while true do
  begin
    line = STDIN.gets
    # heavy processing
  rescue Exception => e
    puts "caught exception #{e}! ohnoes!"
  end
end
不,真的,不要这样做。甚至不要运行它来查看它是否有效。
但是,假设您有一台线程服务器,并且您不希望所有异常:
thread.abort_on_exception = true)。  然后,这在您的连接处理线程中是完全可以接受的:
begin
  # do stuff
rescue Exception => e
  myLogger.error("uncaught #{e} exception while handling connection: #{e.message}")
    myLogger.error("Stack trace: #{backtrace.map {|l| "  #{l}\n"}.join}")
end
上面是Ruby默认异常处理程序的一种变体,它的优点是不会杀死您的程序。Rails在其请求处理程序中执行此操作。
信号异常在主线程中引发。后台线程不会获取它们,因此尝试将它们捕获在那里是没有意义的。
这在生产环境中特别有用,在生产环境中,您不希望程序在出现问题时仅停止运行。然后,您可以将堆栈转储记录到日志中,并添加到您的代码中,以更优雅的方式在调用链中进一步处理特定异常。
还请注意,还有另一个Ruby惯用语具有相同的效果:
a = do_something rescue "something else"在这一行中,如果do_something引发异常,它将被Ruby捕获,丢弃a并被分配"something else"。
一般情况下,不这样做,除非在你特殊情况下,知道你没有必要担心。一个例子:
debugger rescue nil该debugger函数是在代码中设置断点的一种非常不错的方法,但是如果在调试器和Rails之外运行,则会引发异常。从理论上讲,现在您不应该将调试代码留在程序中(pff!没有人这样做!),但是出于某种原因,您可能希望将其保留一段时间,但不要连续运行调试器。
注意:
如果您已经运行了捕获信号异常并忽略它们的其他人的程序,(例如上面的代码),那么:
pgrep ruby或ps | grep ruby,以查找有问题的程序的PID,然后运行kill -9 <PID>。   如果您正在使用别人的程序,无论出于何种原因,这些程序都充斥着这些ignore-exception块,那么将其放在主线顶部是一种可能的解决方案:
%W/INT QUIT TERM/.each { |sig| trap sig,"SYSTEM_DEFAULT" }这将导致程序通过立即终止,绕过异常处理程序而不进行清理来响应正常终止信号 。因此可能导致数据丢失或类似情况。小心!
如果您需要这样做:
begin
  do_something
rescue Exception => e
  critical_cleanup
  raise
end
您实际上可以这样做:
begin
  do_something
ensure
  critical_cleanup
end
在第二种情况下,critical cleanup无论是否引发异常,都会被调用。
kill -9。
                    ensure无论是否引发异常,an 都会运行,而rescue仅在引发异常时才会运行will。
                    请勿rescue Exception => e(也不要重新提出例外)-否则您可能会驶离桥梁。
假设您正在开车(正在运行Ruby)。您最近在空中升级系统上安装了一个新的方向盘(使用eval),但您不知道其中一位程序员对语法感到困惑。
您在桥上,意识到自己要驶向栏杆,所以您向左转。
def turn_left
  self.turn left:
end
哎呀!幸运的是,这可能不是Good ™,Ruby提出了一个SyntaxError。
汽车应该立即停止-对吗?
不。
begin
  #...
  eval self.steering_wheel
  #...
rescue Exception => e
  self.beep
  self.log "Caught #{e}.", :warn
  self.log "Logged Error - Continuing Process.", :info
end
哔哔
警告:捕获到SyntaxError异常。
信息:记录的错误-继续过程。
您会发现什么是错的,你猛踩紧急中断(^C:Interrupt)
哔哔
警告:捕获到中断异常。
信息:记录的错误-继续过程。
是的-没什么帮助。您非常靠近铁路,因此您将汽车停放在了公园(killing:)SignalException。
哔哔
警告:捕获到SignalException异常。
信息:记录的错误-继续过程。
在最后一秒钟,您拉出(kill -9)键,汽车停下来,向前猛撞方向盘(安全气囊无法充气,因为您没有适当地停止程序,因此终止了程序),然后计算机后面的汽车猛撞到它前面的座位上。半满的可乐罐溢出了报纸。后面的杂物被压碎,大部分被蛋黄和牛奶覆盖。该车需要认真维修和清洁。(数据丢失)
希望您有保险(备用)。哦,是的-由于安全气囊没有膨胀,您可能受伤了(被解雇了,等等)。
可是等等!有更多您可能要使用的原因rescue Exception => e!
假设您是那辆汽车,并且如果汽车超过其安全的停止动量,则要确保安全气囊膨胀。
 begin 
    # do driving stuff
 rescue Exception => e
    self.airbags.inflate if self.exceeding_safe_stopping_momentum?
    raise
 end
这是该规则的例外:Exception 只有重新引发例外时,您才能捕获。因此,更好的规则是永不吞咽Exception,并始终重新提出该错误。
但是,使用Ruby之类的语言添加救援很容易被遗忘,并且在重新提出问题之前立即发布救援声明会感到有些不愉快。而你不想要忘记的raise声明。如果这样做,祝您找到这个错误,祝您好运。
值得庆幸的是,Ruby非常棒,您只需使用ensure关键字即可确保代码能够运行。该ensure关键字将不管运行代码-如果一个异常被抛出,如果不是,唯一的例外是,如果世界结束(或其他不可能事件)。
 begin 
    # do driving stuff
 ensure
    self.airbags.inflate if self.exceeding_safe_stopping_momentum?
 end
繁荣!而且该代码无论如何都应该运行。您应该使用的唯一原因rescue Exception => e是,如果您需要访问异常,或者仅希望代码在异常上运行。并记得重新提出该错误。每次。
注意:正如@Niall指出的那样,请确保始终运行。这是件好事,因为有时即使您遇到问题,您的程序也可以骗您,并且不会抛出异常。对于关键任务,例如给安全气囊充气,您需要确保无论发生什么事情都可以发生。因此,每次停车时检查是否引发异常都是一个好主意。尽管在大多数编程情况下,安全气囊的充气并不常见,但实际上在大多数清理任务中还是很常见的。
ensure的替代部分rescue Exception具有误导性-该示例暗示它们是等效的,但是ensure如上所述,无论是否存在异常都将发生,因此现在您的安全气囊将膨胀,因为即使没有发生任何问题,行驶速度超过5英里/小时。
                    这是该规则的一个特例,即您不应捕获任何您不知道如何处理的异常。如果您不知道如何处理,最好让系统的其他部分捕获并处理它。
我刚刚在honeybadger.io上阅读了一篇很棒的博客文章:
为什么你不应该拯救异常
抢救Exception的问题在于,它实际上可以挽救从Exception继承的每个异常。那是....所有人!
这是一个问题,因为Ruby在内部使用了一些异常。它们与您的应用程序没有任何关系,吞下它们会导致不良情况的发生。
以下是一些大问题:
SignalException :: Interrupt-如果您营救了这个,则无法通过按Control-c退出应用程序。
ScriptError :: SyntaxError-吞咽语法错误意味着puts(“ Forgot something)之类的错误将静默失败。
NoMemoryError-想知道程序用完所有RAM后继续运行会发生什么情况?我也不。
begin do_something() rescue Exception => e # Don't do this. This will swallow every single exception. Nothing gets past it. end我猜您真的不想吞下任何这些系统级异常。您只想捕获所有应用程序级错误。异常导致您的代码。
幸运的是,有一个简单的方法可以做到这一点。