3

在我的 Rails 应用程序中,我有一个脚本可以更新数据库中的一些记录。当我发送 SIGTERM 来终止脚本时,它偶尔会在 ActiveRecord 执行查询时收到该信号。这会导致引发 ActiveRecord::StatementInvalid 异常。

我想捕获当它们是 SIGTERM 的结果时发生的 StatementInvalid 异常并退出脚本。如何判断 StatementInvalid 是由于信号而不是其他原因而发生的?

4

3 回答 3

6

如果你捕获了 TERM 信号,我相信你会避免异常。您可以在脚本的开头执行此操作(或者实际上在任何地方执行此操作,但您只需执行一次)。

 Signal.trap("TERM") do
   Kernel.exit!
 end

您收到 StatementInvalid 错误的原因是 Ruby 通过在当前执行位置引发 SIGTERM 异常来处理信号。ActiveRecord 正在捕获异常并将其作为 StatementInvalid 重新抛出。通过设置信号处理程序,Ruby 将执行您的处理程序而不是引发异常。

有关更多信息,请参阅Ruby Signal 文档

于 2009-02-16T02:50:22.427 回答
0

听起来这个“脚本”在 Rails 应用程序的外部(script/runner或类似的?),所以也许你可以解耦“信号处理程序”和“工人”?例如,您可以派生一个子进程/线程/光纤/... 来更新数据库,并向父进程发出信号以指示“现在停止”吗?当然,然后父母必须“指示”孩子停止使用某种适当的机制(不是SIGTERM;-))。

于 2009-02-14T00:26:46.137 回答
0

这不是对 OP 的确切答案,但是,您可以控制退出点 - 程序只有在到达您定义的退出点后才会退出。

time_to_die=false

# Prevent abrupt stopping of the daemon.
Signal.trap("TERM") { time_to_die=true; "SIG_IGN" }   

loop {
  .
  .
  exit_gracefully if time_to_die
  .
  .
}

def exit_gracefully
   #Cleaning up..
   $log.log "#{Time.now} TERM signal received. Exiting.."
   $db.close
   exit
 end
于 2010-02-01T09:29:53.983 回答