Избегайте отображения обратной трассировки при запуске Sinatra на уже занятом порту - PullRequest
0 голосов
/ 20 октября 2018

Как правильно запретить Sinatra отображать полную обратную трассировку, когда не удается правильно запустить сервер (например, из-за того, что порт уже используется)?

Это пример sinatraapp:

# test.rb
require 'sinatra'
require 'bundler/inline'

gemfile do
  gem 'sinatra'
  gem 'puma'
end

set :bind, "0.0.0.0"
set :port, 3000

get '/' do
  "hello"
end

Затем, запустив его с ruby test.rb один раз, чтобы занять порт.

Затем, запустив его снова в другом окне терминала, и отобразится полная трассировка ошибки:

$ ruby test.rb
== Sinatra (v2.0.4) has taken the stage on 3000 for development with backup from Puma
Puma starting in single mode...
* Version 3.12.0 (ruby 2.5.0-p0), codename: Llamas in Pajamas
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:3000
== Someone is already performing on port 3000!
Traceback (most recent call last):
        5: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/main.rb:26:in `block in <module:Sinatra>'
        4: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1464:in `run!'
        3: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1464:in `ensure in run!'
        2: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1439:in `quit!'
        1: from /store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/launcher.rb:147:in `stop'
/store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/single.rb:27:in `stop': undefined method `stop' for nil:NilClass (NoMethodError)
Traceback (most recent call last):
        3: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1545:in `block in setup_traps'
        2: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1439:in `quit!'
        1: from /store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/launcher.rb:147:in `stop'
/store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/single.rb:27:in `stop': undefined method `stop' for nil:NilClass (NoMethodError)

Поскольку я использую его в качестве встроенного сервера, я хотел бы, чтобы вывод просто и с дружественной ошибкой, которую уже показывает Sinatra:

== Someone is already performing on port 3000!

, и во избежание показатрассировка.

Ответы [ 3 ]

0 голосов
/ 21 октября 2018

Вы можете проверить, используется ли порт, попытавшись прослушать порт, прежде чем позволить Sinatra и Puma вступить во владение.Это не на 100% эффективно, потому что есть состояние гонки, при котором вы можете открывать и закрывать порт, но до завершения инициализации Sinatra / Puma приходит какой-то другой процесс, который прослушивает тот же порт, но он должен работать в вашем случае использования (который выглядит как косметический хак).

Вставьте этот код в любое место в test.rb:

require 'socket'
include Socket::Constants

begin
  # Open and close the port
  socket = Socket.new(AF_INET, SOCK_STREAM, 0)
  sockaddr = Socket.pack_sockaddr_in(3000, '0.0.0.0')
  socket.bind(sockaddr)
  socket.listen(1)
  socket.close
rescue Errno::EADDRINUSE => error
  # Traps the same error that is trapped by Sinatra and exits if raised
  puts error.message
  exit
end

Начните первый с ruby test.rb:

== Sinatra (v2.0.4) has taken the stage on 3000 for development with backup from Puma
Puma starting in single mode...
* Version 3.12.0 (ruby 2.6.0-p-1), codename: Llamas in Pajamas
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop

Начните второй с ruby test.rb:

Address already in use - bind(2) for 0.0.0.0:3000

Вы можете выделить то, что вы хотите напечатать на консоли внутри блока rescue.

0 голосов
/ 23 октября 2018

Похоже, что это вызвано проблемой с Puma , которая устранена этим PR .

0 голосов
/ 20 октября 2018

Ruby по умолчанию выводит сообщения об ошибках в STDOUT.Но если вы работаете в * nix системе, вы можете сделать это:

ruby test.rb > /dev/null 2>&1

Для Windows вы, вероятно, можете сделать

ruby test.rb > NULL

windows powershell

ruby test.rb > $null

, нодля окон также см. Существует ли / dev / null в Windows?

Но если вы хотите программно подавить вывод при работе сервера, это должно работать на * nix, но не обязательно на Windows

# test.rb
require 'sinatra'
require 'bundler/inline'

gemfile do
  gem 'sinatra'
  gem 'puma'
end

set :bind, "0.0.0.0"
set :port, 3000

get '/' do
  "hello"
end

unless `ps aux | grep sinatra`.match('tcp://0.0.0.0:3000')
  STDOUT.reopen('/dev/null', 'w')
  STDERR.reopen('/dev/null', 'w')
end

См. поддержка вывода на консоль с помощью ruby ​​

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...