Ruby 检查程序当前是否正在关闭
Ruby check whether program is currently being closed
如何检查 Ruby 中的当前脚本是否正在关闭?
特别是,如果程序正在关闭,我想将 @reconnect
设置为 false
,不再允许 web-socket 重新连接。我试了Signal.trap("TERM")
,但好像不行。
@reconnect
是 WebsocketClient class 内部的一个实例变量,我无法在 class.
之外的脚本中直接更改它
class WebsocketClient
def ws_closed(event)
$logger.warn "WS CLOSED"
Signal.trap("TERM") {
@stop = true
@reconnect = false
}
unless $reauth
if @stop
EM.stop
elsif @reconnect
$logger.warn "Reconnecting..."
EM.add_timer(@reconnect_after){ connect! }
end
end
end
end
at_exit {
$logger.fatal "Application terminated. Shutting down gracefully..."
# ...
# Do some exit work...
# ...
exit!
}
CTRL-C 输出
01-02-2018 12:00:54.59 WARN > WS CLOSED
01-02-2018 12:00:54.595 WARN > Reconnecting...
01-02-2018 12:00:54.596 FATAL > Application terminated. Shutting down gracefully..
请参阅下面摘自我的回答 Here 但似乎与您的问题比当前所附的问题更相关:
最好的选择可能比信号捕获更容易一些。 Kernel
Module
实际上为您提供了一个 #at_exit
方法,该方法将在程序实际退出之前执行。
用法:(来自Kernel#at_exit
Docs)
def do_at_exit(str1)
at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit
"produces:"
goodbye cruel world
如您所见,您可以定义多个处理程序,这些处理程序将在程序退出时以相反的顺序执行。
由于 Kernel
包含在 Object
中,您可以像
一样处理 Object
细节
class People
at_exit {puts "The #{self.name} have left"}
end
exit
# The People have left
甚至在实例上
p = People.new
p.send(:at_exit, &->{puts "We are leaving"})
# We are leaving
# The People have left
此外,对于更具体的基于 Object
的实现,您可以查看 ObjectSpace.define_finalizer
。
用法示例:
class Person
def self.finalize(name)
proc {puts "Goodbye Cruel World -#{name}"}
end
def initialize(name)
@name = name
ObjectSpace.define_finalizer(self, self.class.finalize(@name))
end
end
用法:
p = Person.new("engineersmnky")
exit
# Goodbye Cruel World -engineersmnky
这可能不是您想要的,因为当 Object
也被垃圾收集时它会触发(对于临时对象来说不是很好)但是如果您有应该存在于整个应用程序中的对象,这可能仍然可以像 at_exit 一样使用。范例
# requiring WeakRef to allow garbage collection
# See: https://ruby-doc.org/stdlib-2.3.3/libdoc/weakref/rdoc/WeakRef.html
require 'weakref' #
p1 = Person.new("Engineer")
p2 = Person.new("Engineer's Monkey")
p2 = WeakRef.new(p2)
GC.start # just for this example
# Goodbye Cruel World -Engineer's Monkey
#=> nil
p2
#=> WeakRef::RefError: Invalid Reference - probably recycled
exit
# Goodbye Cruel World -Engineer
如您所见,为 p2
定义的终结器被触发,因为 Person
已被 gc,但程序尚未退出。 p1
的终结器一直等到退出才触发,因为它在整个应用程序中保留了它的引用。
如何检查 Ruby 中的当前脚本是否正在关闭?
特别是,如果程序正在关闭,我想将 @reconnect
设置为 false
,不再允许 web-socket 重新连接。我试了Signal.trap("TERM")
,但好像不行。
@reconnect
是 WebsocketClient class 内部的一个实例变量,我无法在 class.
class WebsocketClient
def ws_closed(event)
$logger.warn "WS CLOSED"
Signal.trap("TERM") {
@stop = true
@reconnect = false
}
unless $reauth
if @stop
EM.stop
elsif @reconnect
$logger.warn "Reconnecting..."
EM.add_timer(@reconnect_after){ connect! }
end
end
end
end
at_exit {
$logger.fatal "Application terminated. Shutting down gracefully..."
# ...
# Do some exit work...
# ...
exit!
}
CTRL-C 输出
01-02-2018 12:00:54.59 WARN > WS CLOSED
01-02-2018 12:00:54.595 WARN > Reconnecting...
01-02-2018 12:00:54.596 FATAL > Application terminated. Shutting down gracefully..
请参阅下面摘自我的回答 Here 但似乎与您的问题比当前所附的问题更相关:
最好的选择可能比信号捕获更容易一些。 Kernel
Module
实际上为您提供了一个 #at_exit
方法,该方法将在程序实际退出之前执行。
用法:(来自Kernel#at_exit
Docs)
def do_at_exit(str1)
at_exit { print str1 }
end
at_exit { puts "cruel world" }
do_at_exit("goodbye ")
exit
"produces:"
goodbye cruel world
如您所见,您可以定义多个处理程序,这些处理程序将在程序退出时以相反的顺序执行。
由于 Kernel
包含在 Object
中,您可以像
Object
细节
class People
at_exit {puts "The #{self.name} have left"}
end
exit
# The People have left
甚至在实例上
p = People.new
p.send(:at_exit, &->{puts "We are leaving"})
# We are leaving
# The People have left
此外,对于更具体的基于 Object
的实现,您可以查看 ObjectSpace.define_finalizer
。
用法示例:
class Person
def self.finalize(name)
proc {puts "Goodbye Cruel World -#{name}"}
end
def initialize(name)
@name = name
ObjectSpace.define_finalizer(self, self.class.finalize(@name))
end
end
用法:
p = Person.new("engineersmnky")
exit
# Goodbye Cruel World -engineersmnky
这可能不是您想要的,因为当 Object
也被垃圾收集时它会触发(对于临时对象来说不是很好)但是如果您有应该存在于整个应用程序中的对象,这可能仍然可以像 at_exit 一样使用。范例
# requiring WeakRef to allow garbage collection
# See: https://ruby-doc.org/stdlib-2.3.3/libdoc/weakref/rdoc/WeakRef.html
require 'weakref' #
p1 = Person.new("Engineer")
p2 = Person.new("Engineer's Monkey")
p2 = WeakRef.new(p2)
GC.start # just for this example
# Goodbye Cruel World -Engineer's Monkey
#=> nil
p2
#=> WeakRef::RefError: Invalid Reference - probably recycled
exit
# Goodbye Cruel World -Engineer
如您所见,为 p2
定义的终结器被触发,因为 Person
已被 gc,但程序尚未退出。 p1
的终结器一直等到退出才触发,因为它在整个应用程序中保留了它的引用。