0

In my Ruby on Rails dev environment, I am starting Rails and Unicorn via Foreman in the typical way:

(Procfile:)

web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

I am also running Pow. But not as a webserver. I'm just using Pow to direct http requests from mydomain.dev (port 80) to the port Unicorn is listening on.

You can do this by creating a pow file (mydomain.dev) containing the port number Unicorn is running on.

Given this setup, is it possible in my rails code to know what the port I started Unicorn on?

I'm only wanting to know this in my dev environment, it's not a production issue.

In my Rails code, I've tried a few different things, but none of them work:

  • Unicorn::Configurator::RACKUP[:port] - returned nothing
  • Rails::Server.new.options[:Port] - doesn't exist in Rails 4
  • Rack::Server.new.options[:Port] - returns default rack port (9292) not the one configured for this rack instance.

    Is there a way to get the current rack instance from rails?

  • request.port - returns 80, which is the port that Pow is listening on. Pow is routing http traffic to Unicorn, which is on a different port.

None of these give me the port that Unicorn is running on.

Any ideas?

EDIT If you're wondering why I want to know this, it's because in my dev environment, I'm trying to dynamically create configuration files for Pow, so I can route http requests to Unicorn on the correct port.

asgeo1
  • 9,028
  • 6
  • 63
  • 85

4 Answers4

0

If you're responding to a request in a controller or view, use the request object - this should work, although you say it does not:

request.port

If you're in an initialiser :

Rails::Server.new.options[:Port]

How to find the local port a rails instance is running on?

Community
  • 1
  • 1
adamliesko
  • 1,887
  • 1
  • 14
  • 21
  • request.port returns 80. I think that's because I'm using Pow, and Pow is listening on 80, and then forwards the traffic to Unicorn on a different port. – asgeo1 Jul 29 '15 at 08:29
  • `Rails::Server.new.options[:Port]` is the same as `Rack::Server.new.options[:Port]`, which is what is used in newer versions of Rails. I didn't know that only worked from an initializer, so I'll try that out now. – asgeo1 Jul 29 '15 at 08:30
  • I don't think it matters where you call `Rack::Server.new.options[:Port]`, it works outside of initializers too. But that will return the default port for a rack server, which is 9292. It doesn't return the actual rack server instance with the configured port. – asgeo1 Jul 29 '15 at 08:34
0

You should just be able to access it via ENV['PORT'], given it's value has been set to the $PORT environment variable.

Glenn Gillen
  • 471
  • 2
  • 7
  • No, that won't work. Because $PORT is being set by Foreman in the `.foreman` file. I *was* using that - however it doesn't allow me to have different $PORT values for development and testing environments. – asgeo1 Jul 30 '15 at 09:05
  • The question was: "to know what the port I started Unicorn on" and you said "`$PORT` is being set by Foreman'. Given `foreman` is starting `Unicorn`, why isn't this exactly what you need? You can have different ports by supplying different values to `foreman` on the command line: `$ foreman start --port 2000`. I've never used `foreman` for running my tests, the standard ruby tooling + `bundler` typically give me everything I need without the extract overhead of a process manager. – Glenn Gillen Jul 31 '15 at 00:04
  • OK, I didn't know I could pass the port to Foreman on the command line. I think I would want to avoid that if possible though. – asgeo1 Jul 31 '15 at 00:55
  • I think my idea of running the test server via foreman is not a good anyway. I'm mainly trying to run feature tests via selenium. I don't like how the test server that Capybara starts works, and wanted it to use the same unicorn setup that the dev environment uses, but just on a different port. The issue was is my app dynamically creates virtual directory files for Pow, and it needs to know the correct port. Anyway... I sort of have something working now. Thanks for your comments. – asgeo1 Jul 31 '15 at 00:55
0

Probably a bad idea, but whatever:

uport = `netstat -n --listening --tcp -p | grep unicorn | sed 's/.*:\([0-9]*\) .*/\1/'`
jotik
  • 17,044
  • 13
  • 58
  • 123
hoffmanc
  • 614
  • 9
  • 16
0

I've sort of found a way to do this.

  1. Create separate config files for Unicorn. unicorn.development.rb and unicorn.test.rb
  2. Install the dotenv-rails gem
  3. Inside my unicorn config files, do something like this: # unicorn.development.rb:

    require "dotenv"
    Dotenv.load(
      "./.env.local",
      "./.env.development",
      "./.env"
    )
    
    if ENV['UNICORN_PORT'].nil?
      throw 'UNICORN_PORT not set in environment!'
    end
    
    worker_processes 3
    timeout 30
    preload_app true
    
    listen ENV['UNICORN_PORT'], backlog: 64
    
    ... rest of unicorn config...
    
    
    
    
    # unicorn.testing.rb:
    
    require "dotenv"
    Dotenv.load(
      "./.env.local",
      "./.env.testing",
      "./.env"
    )
    
    if ENV['UNICORN_PORT'].nil?
      throw 'UNICORN_PORT not set in environment!'
    end
    
    worker_processes 3
    timeout 30
    preload_app true
    
    listen ENV['UNICORN_PORT'], backlog: 64
    
    ... rest of unicorn config...
    
  4. In my .env.development and .env.testing environment files, set the UNICORN_PORT environment variable

  5. Make sure you use the correct Unicorn config file to start the app. This can be done by using separate Procfiles for dev and testing.

    # Procfile.dev
    web: bundle exec unicorn -c ./config/unicorn.development.rb
    
    # Procfile.testing
    web: bundle exec unicorn -c ./config/unicorn.testing.rb
    

This appears to mostly work, but is not without it's issues...

asgeo1
  • 9,028
  • 6
  • 63
  • 85