开始救援没有发现错误

Posted

技术标签:

【中文标题】开始救援没有发现错误【英文标题】:Begin Rescue not catching error 【发布时间】:2011-03-11 05:40:24 【问题描述】:

我正在使用一些包含在 begin - rescue 块中的 ruby​​ 代码,但不知何故它仍然会崩溃。

代码块如下所示:

# Retrieve messages from server
def get_messages
  @connection.select('INBOX')
  @connection.uid_search(['ALL']).each do |uid|
    msg = @connection.uid_fetch(uid,'RFC822').first.attr['RFC822']
    begin
      process_message(msg)
      add_to_processed_folder(uid) if @processed_folder
    rescue
       handle_bogus_message(msg)
    end
    # Mark message as deleted 
    @connection.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
  end
end

鉴于此代码,我假设如果 process_messageadd_to_processed_folder 无法执行,则救援将启动并调用 handle_bogus_message。话虽如此,我在生产环境中运行此代码,有时当我“收到”一封电子邮件(这是从 rake 任务运行的)时,它会因 SyntaxError 而死。

要查看错误消息,请查看http://pastie.org/1028479,而不是它所指的 process_message 与上面的 process_message 相同。 begin - rescue 不会捕获此异常有什么原因吗?

【问题讨论】:

【参考方案1】:

rescue 不带参数只会挽救从StandardError 继承的异常。要拯救SyntaxError,请使用rescue SyntaxError

如here 和here 解释的那样,为了挽救所有异常,您将使用rescue Exception,但请注意这是一个坏主意(这就是为什么它不是rescue 的默认行为的原因)。尤其是这部分:

救援中断可防止用户使用 CTRLC 退出程序。

救援 SignalException 会阻止程序正确响应信号。除非 kill -9,否则它将无法杀死。

【讨论】:

rescue 默认不救援Exceptions 的原因是他们通常被认为过于严重而无法救援。【参考方案2】:

rescue 不带任何参数接受由 StandardError 类引发的异常。您的错误类型是 SyntaxError,它继承自另一个名为 ScriptError 的类。所有这些错误类都是异常类的子类。所以 sepp2k 建议使用rescue Exception 来捕获各种异常。

【讨论】:

以上是关于开始救援没有发现错误的主要内容,如果未能解决你的问题,请参考以下文章

CentOS 7 单用户模式+救援模式

Ruby救援语法错误

从 Mysql2::Error 中救援

以 DRY 方式将多个错误类传递给 ruby​​ 的救援子句

如何使用救援模式进行恢复错误删除的程序或者库文件所以以来的共享库

安装glibc错误链接导致系统崩溃,u盘启动紧急救援模式下修复系统。