我试图在ruby中创建一个可以从命令行启动的应用程序,它做了两件事:运行一个连续的工作(loop
和sleep
运行一些动作[远程在第二个线程中使用一个线程和sinatra进行解析])。我的代码(简化)看起来像这样:
require 'sinatra'
class MyApp < Sinatra::Base
get '/' do
"Hello!"
end
end
threads = []
threads << Thread.new do
loop do
# do something heavy
sleep 10
end
end
threads << Thread.new do
MyApp.run!
end
threads.each { |t| t.join }
上面的代码确实很好地完成了它的工作 - sinatra应用程序在4567端口下启动,do something heavy
任务每10秒启动一次。但是,我无法杀死那个剧本。
我用ruby app.rb
运行它但是用ctrl + c查杀它是行不通的。它只杀死sinatra线程但第二个仍在运行,为了停止脚本,我需要关闭终端窗口。
我试图杀死SIGNINT上的所有主题,但它也没有按预期工作
trap "SIGINT" do
puts "Exiting"
threads.each { |t| Thread.kill t }
exit 130
end
你能帮我解决这个问题吗?提前谢谢。
答案 0 :(得分:2)
要捕获ctrl-c,请将“SIGINT”更改为“INT”。
trap("INT") {
puts "trapping"
threads.each{|t|
puts "killing"
Thread.kill t
}
}
配置Sinatra以跳过捕获陷阱:
class MyApp < Sinatra::Base
configure do
set :traps, false
end
...
参考:Ruby Signal module
列出可用的Ruby信号:Signal.list.keys
(当我运行你的代码并捕获INT时,我确实得到一个Sinatra套接字警告“已经在使用中”。我认为这对你的目的来说很好,或者你可以通过Sinatra优雅关闭来解决这个问题。见{{3 }})
答案 1 :(得分:0)
晚了聚会,但是Trap有一个很大的缺点-网络服务器会覆盖它。例如,彪马设置了几个陷阱,这些陷阱基本上使您永远不会被召唤。
最好的解决方法是使用at_exit
,它可以多次定义,并且Ruby确保所有块都被调用。我还没有测试过它是否适合您的情况。