我能否在Sinatra应用程序中停止Sinatra?

3
我想了解如何在Sinatra应用程序内部以编程方式退出应用程序。 (有另一个SO线程可以停止外部应用程序。)
我希望使用Sinatra作为接收控制和配置命令的手段,同时我的应用程序执行与Sinatra无关的任务。 我想要一个控制命令是“exit”。 Ruby的“exit”方法似乎只会导致Sinatra恢复并恢复。 我在base.rb中发现了这个问题,我认为它证实了这一点:
at_exit { Application.run! if $!.nil? && Application.run? }

到目前为止,我发现唯一的方法是调用Ruby的exit!方法,但这将绕过exit钩子,并且不是一个很干净的解决方案。是否有办法以编程方式告诉Sinatra停止?

说实话,我不记得8年前发布这个问题时需要它做什么。我想我可能想要在满足某些外部条件时终止。我认为@bigtunacan的方法是最好的(不幸的是,因为我不太喜欢猴子补丁)。我可以启动一个线程来进行检查,并在必要时调用exit!。(续) - Keith Bennett
这将绕过所有的退出钩子,除了Sinatra的,我想避免这种情况。 - Keith Bennett
4个回答

3
我使用了以下代码:
# Exit 'correctly'
get '/exit' do
  # /exit causes:
  # 15:20:24 web.1  | Damn!
  # 15:20:24 web.1  | exited with code 1
  Process.kill('TERM', Process.pid)
end

# Just terminate
get '/fail' do
  Process.kill('KILL', Process.pid)
end

请查看config.ru中的at_exit函数,它可以处理TERM信号。
at_exit do
  puts 'Damn!'
  exit false
end

完整示例在这里。祝好。

这样做是否与调用 exit! 的行为完全相同? - Keith Bennett

1
这有点违背了Sinatra的原则,但这只是Ruby,你可以通过打开类/猴子补丁来轻松实现。只需重新打开base.rb中的at_exit方法并覆盖Application.run!行为即可。

1

Sinatra::Base::quit! 或其别名 ::stop! 是你要寻找的:

require 'sinatra'

get '/quit' do
  self.class.quit!
end

get '/stop' do
  self.class.stop!
end

感谢您的建议。正如问题中所提到的,我需要从服务器内部调用它,而不是让客户端可用。 - Keith Bennett

1
为什么不直接抛出异常呢?这将意味着$!不是nil,因此at_exit处理程序将不会重新启动Sinatra。
一种简单的方法是运行failraise。您还可以传递消息,例如fail "由于x退出"

谢谢,这个可以行得通,但会在启动Sinatra的终端中产生错误输出,并且该输出不容易与由真正错误导致的输出区分开来。 - Keith Bennett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接