Getting the Hostname or IP in Ruby on Rails

2019-01-03 08:45发布

I'm in the process of maintaining a Ruby on Rails app and am looking for an easy way to find the hostname or IP address of the box I'm on (since it's a VM and new instances may have different hostnames or IP addresses). Is there a quick and easy way to do this in Ruby on Rails?

Edit: The answer below is correct but the clarification Craig provided is useful (see also provided link in answer):

The [below] code does NOT make a connection or send any packets (to 64.233.187.99 which is google). Since UDP is a stateless protocol connect() merely makes a system call which figures out how to route the packets based on the address and what interface (and therefore IP address) it should bind to. addr() returns an array containing the family (AF_INET), local port, and local address (which is what we want) of the socket.

12条回答
一夜七次
2楼-- · 2019-01-03 09:40

Hostname

A simple way to just get the hostname in Ruby is:

require 'socket'
hostname = Socket.gethostname

The catch is that this relies on the host knowing its own name because it uses either the gethostname or uname system call, so it will not work for the original problem.

Functionally this is identical to the hostname answer, without invoking an external program. The hostname may or may not be fully qualified, depending on the machine's configuration.


IP Address

Since ruby 1.9, you can also use the Socket library to get a list of local addresses. ip_address_list returns an array of AddrInfo objects. How you choose from it will depend on what you want to do and how many interfaces you have, but here's an example which simply selects the first non-loopback IPV4 IP address as a string:

require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
查看更多
爷、活的狠高调
3楼-- · 2019-01-03 09:41

The accepted answer works but you have to create a socket for every request and it does not work if the server is on a local network and/or not connected to the internet. The below, I believe will always work since it is parsing the request header.

request.env["SERVER_ADDR"]
查看更多
在下西门庆
4楼-- · 2019-01-03 09:41

try: Request.remote_ip

remote_ip()

Determine originating IP address. REMOTE_ADDR is the standard but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR are set by proxies so check for these if REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma- delimited list in the case of multiple chained proxies; the last address which is not trusted is the originating IP.

Update: Oops, sorry I misread the documentation.

查看更多
男人必须洒脱
5楼-- · 2019-01-03 09:44

From coderrr.wordpress.com:

require 'socket'

def local_ip
  orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true  # turn off reverse DNS resolution temporarily

  UDPSocket.open do |s|
    s.connect '64.233.187.99', 1
    s.addr.last
  end
ensure
  Socket.do_not_reverse_lookup = orig
end

# irb:0> local_ip
# => "192.168.0.127"
查看更多
三岁会撩人
6楼-- · 2019-01-03 09:45
io = IO.popen('hostname')
hostname = io.readlines

io = IO.popen('ifconfig')
ifconfig = io.readlines
ip = ifconfig[11].scan(/\ \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\ /)

The couple of answers with require 'socket' look good. The ones with request.blah_blah_blah assume that you are using Rails.

IO should be available all the time. The only problem with this script would be that if ifconfig is output in a different manor on your systems, then you would get different results for the IP. The hostname look up should be solid as Sears.

查看更多
We Are One
7楼-- · 2019-01-03 09:46

This IP address used here is Google's, but you can use any accessible IP.

require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
查看更多
登录 后发表回答