在我的Rails应用程序中,我有一个更新数据库中某些记录的脚本。当我发送SIGTERM来杀死脚本时,它偶尔会在ActiveRecord执行查询时收到该信号。这会导致引发ActiveRecord :: StatementInvalid异常。
我想捕获当它们是SIGTERM的结果并退出脚本时发生的StatementInvalid异常。如何判断由于信号而发生StatementInvalid而不是出于其他原因?
答案 0 :(得分:5)
如果你捕获了TERM信号,我相信你会避免这个例外。您可以在脚本开头执行此操作(或者在任何地方执行此操作,但您只需执行一次)。
Signal.trap("TERM") do
Kernel.exit!
end
您收到StatementInvalid错误的原因是Ruby通过在当前执行的位置引发SIGTERM异常来处理信号。 ActiveRecord正在捕获异常并将其重新抛出为StatementInvalid。通过设置Signal处理程序,Ruby将执行您的处理程序而不是引发异常。
有关详细信息,请参阅Ruby Signal documentation。
答案 1 :(得分:0)
听起来这个“脚本”在Rails应用程序外部(script/runner
或类似的?),所以也许你可以解耦“信号处理程序”和“工作者”?例如,您可以分叉子进程/线程/光纤/ ...进行数据库更新,并通知父进程指示“立即停止”?当然,父母必须“发信号”孩子停止使用某种适当的机制(不是SIGTERM
; - ))。
答案 2 :(得分: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