如何检测Ruby脚本关闭状态并禁用WebSocket重连?Signal.trap无效求助
解决Ruby脚本关闭时停止WebSocket重连的问题
我来帮你梳理下问题所在,以及对应的解决方案:
问题分析
你遇到的几个核心问题:
- 信号监听错配:按下
CTRL-C发送的是INT信号,不是TERM信号,所以之前监听TERM自然不会触发。 - 信号陷阱设置时机滞后:你在
ws_closed方法里才注册信号陷阱,但这个方法只有当WebSocket连接关闭时才会执行,程序退出时可能连接还没断开,陷阱根本没被注册上。 - 实例变量封装限制:
@reconnect是类内部的实例变量,外部直接修改违反封装原则,也没法直接访问。
解决方案
我们可以通过封装停止方法+提前注册多信号监听+**结合at_exit**来解决:
1. 给WebsocketClient添加停止重连的方法
在类内部封装修改实例变量的逻辑,提供一个对外的接口:
class WebsocketClient def initialize @reconnect = true @stop = false @reconnect_after = 5 # 根据你的实际需求调整 end # 新增:对外暴露停止重连的方法 def stop_gracefully @reconnect = false @stop = true # 确保EventMachine事件循环停止(如果还在运行) EM.stop if EM.reactor_running? $logger.warn "WebSocket reconnect disabled, stopping event loop..." end def ws_closed(event) $logger.warn "WS CLOSED" if @stop EM.stop elsif @reconnect $logger.warn "Reconnecting..." EM.add_timer(@reconnect_after){ connect! } end end # 假设你的连接方法 def connect! # 这里写你的WebSocket连接逻辑 end end
2. 在脚本初始化阶段注册信号监听
在创建WebsocketClient实例之后,立即监听INT(CTRL-C)和TERM(kill命令)信号:
# 创建客户端实例 client = WebsocketClient.new # 监听退出信号 ["INT", "TERM"].each do |signal| Signal.trap(signal) do $logger.warn "Received #{signal} signal, initiating graceful shutdown..." client.stop_gracefully # 触发at_exit逻辑后退出 exit end end
3. 完善at_exit块
确保即使信号监听没触发(比如程序正常结束),也能调用停止方法:
at_exit { $logger.fatal "Application terminated. Shutting down gracefully..." # 检查client是否存在,避免未初始化的情况 client.stop_gracefully if defined?(client) # 其他退出清理工作... }
为什么这样有效?
- 信号监听覆盖全面:同时监听
INT和TERM,覆盖了手动按CTRL-C和通过kill命令终止程序的场景。 - 封装符合原则:通过类方法修改内部实例变量,既保证了数据安全,又提供了对外操作的接口。
- 时机正确:信号陷阱在程序启动时就注册,无论程序何时退出都能触发。
内容的提问来源于stack exchange,提问作者Ilya Cherevkov
相关产品推荐
相关产品推荐

