Как мне демонизировать сервер ruby из кода? - PullRequest
3 голосов
/ 25 апреля 2020
handler = Rack::Handler::Thin
#driver = Selenium::WebDriver.for :firefox

class RackApp
  def call(env)
    req = Rack::Request.new(env)
    case req.path_info
    when /hello/
      [200, {"Content-Type" => "text/html"}, [render_erb]]
    when /goodbye/
      [500, {"Content-Type" => "text/html"}, ["Goodbye Cruel World!"]]
    else
      [404, {"Content-Type" => "text/html"}, ["I'm Lost!"]]
    end
  end

  def render_erb
    raw = File.read('template/tipsters.html.erb')
    ERB.new(raw).result(binding)
  end
end
handler.run(RackApp.new, {server: 'sfsefsfsef', daemonize: true, pid: "/piddycent.pid"})

puts "hellllllllllllllllllllllllllllllllllllllllllo"

Я пытаюсь создать простое приложение для моего p c, которое выводит графики в браузере. Я пытаюсь использовать селен, чтобы перейти к localhost после того, как тонкий сервер был демонизирован. К сожалению, он не деамонизируется, и «hellllllllllllllllllllo» выводится на терминал только тогда, когда я отменяю процесс из терминала, то есть тонкий сервер не демонизируется.

Проблема в том, что параметры имеют sh, похоже, игнорируется.

Так что да, любой вклад в то, почему handler.run игнорирует мои параметры, приветствуется sh. Никаких ошибок, это просто игнорирует мои параметры ha sh.

Согласно документации https://www.rubydoc.info/gems/rack/Rack/Server daemonize это вариант?

1 Ответ

1 голос
/ 26 апреля 2020

Я думаю, что проблема здесь связана с недоразумением. Когда мы говорим о демонизации процесса , мы, по сути, говорим: «Этот процесс теперь будет работать в фоновом режиме независимо от любого другого процесса». Это может быть достигнуто, например, путем разветвления процесса для создания нового процесса.

Похоже, именно это вы и собираетесь делать здесь: запустите приложение Ruby, которое запускает новое приложение Rack, которое подключается к отдельному процессу, а затем возвращает управление вашему приложению Ruby, чтобы теперь у вас одновременно работали приложение Rack и приложение Ruby, чтобы вы могли использовать Selenium для просмотра приложения Rack.

Это не не происходит автоматически. Доступ к параметрам демона в Thin возможен, если вы запускаете приложение с помощью командной строки . (потому что вы запускаете новый процесс) Но нет никакого автоматизированного c процесса, разветвляющего , вероятно потому, что это приведет к множеству запутанных проблем. (т. е. если вы запустите свое приложение один раз и подключите новый Thin-сервер к порту 3000, а затем приложение Ruby завершит работу и попытаетесь запустить его снова, у вас уже будет разветвленный Thin-сервер, работающий на порту 3000 и пытающийся запуск нового приведет к ошибке, поскольку используется порт 3000)

По сути, если вы хотите запустить демонизированный тонкий сервер, запустите его с помощью thin CLI. Если вы хотите запустить тонкий сервер ad-ho c в другом приложении, запустите его, как описано выше.

И это, кажется, приводит к реальному ответу: ваше объяснение и пример кода показывают, что вы на самом деле не нужно, чтобы демонизированный тонкий сервер работал в фоновом режиме. Вам нужен Тонкий сервер, который работает в отдельном потоке и возвращает управление основному потоку, чтобы вы могли использовать Selenium, а когда ваше приложение завершает работу, Тонкий сервер также завершает работу.

Если я ошибаюсь, и если вам действительно нужен демонизированный Тонкий сервер, то вы поступаете неправильно. Вы должны использовать Thin-сервер как одно приложение, а приложение Selenium - как другое. (запускать и управлять ими отдельно, а не как одно Ruby приложение)

Но если я прав в этом, то это должно быть так просто:

require 'rack'
require 'thin'
require 'httparty' # used for demonstration purposes only

class RackApp
  def call(env)
    case Rack::Request.new(env).path_info
    when //
      [200, {"Content-Type" => "text/html"}, 'Hello World']
    end
  end
end

threads = []

# First start the Thin server
threads << Thread.new { Rack::Handler::Thin.run(RackApp.new) }

# Then sleep long enough for it to start before making an HTTP request
threads << Thread.new { sleep 2; puts HTTParty.get('http://localhost:8080/').response.body }

threads.each(&:join)

puts 'Back in the main thread'

Вывод в консоли:

Thin web server (v1.7.2 codename Bachmanity)
Maximum connections set to 1024
Listening on localhost:8080, CTRL+C to stop
Hello World

Вам необходимо заменить вызов HTTParty.get своими звонками в Selenium.

Возможно, это не то решение, которое вам нужно, потому что вы не будете смотрите Back in the main thread до тех пор, пока не нажмете ^C, даже если поток Selenium завершил всю работу, которую он должен выполнить, потому что тонкий поток все еще работает:

Thin web server (v1.7.2 codename Bachmanity)
Maximum connections set to 1024
Listening on localhost:8080, CTRL+C to stop
Hello World
^CStopping ...
Back in the main thread

Если вы предпочитаете, чтобы * Приложение 1047 * завершает работу после завершения работы Selenium, вы можете изменить его на что-то вроде этого:

Thread.new { Rack::Handler::Thin.run(RackApp.new) }

selenium_thread = Thread.new { sleep 2; puts HTTParty.get('http://localhost:8080/').response.body }
selenium_thread.join

puts 'Back in the main thread'

И тогда вы увидите нечто подобное, когда приложение Ruby завершит работу сразу после печати Back in the main thread:

Thin web server (v1.7.2 codename Bachmanity)
Maximum connections set to 1024
Listening on localhost:8080, CTRL+C to stop
Hello World
Back in the main thread
...