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条回答
Ridiculous、
2楼-- · 2019-01-03 09:19

You will likely find yourself having multiple IP addresses on each machine (127.0.0.1, 192.168.0.1, etc). If you are using *NIX as your OS, I'd suggest using hostname, and then running a DNS look up on that. You should be able to use /etc/hosts to define the local hostname to resolve to the IP address for that machine. There is similar functionality on Windows, but I haven't used it since Windows 95 was the bleeding edge.

The other option would be to hit a lookup service like WhatIsMyIp.com. These guys will kick back your real-world IP address to you. This is also something that you can easily setup with a Perl script on a local server if you prefer. I believe 3 lines or so of code to output the remote IP from %ENV should cover you.

查看更多
对你真心纯属浪费
3楼-- · 2019-01-03 09:27

A server typically has more than one interface, at least one private and one public.

Since all the answers here deal with this simple scenario, a cleaner way is to ask Socket for the current ip_address_list() as in:

require 'socket'

def my_first_private_ipv4
  Socket.ip_address_list.detect{|intf| intf.ipv4_private?}
end

def my_first_public_ipv4
  Socket.ip_address_list.detect{|intf| intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast? and !intf.ipv4_private?}
end

Both return an Addrinfo object, so if you need a string you can use the ip_address() method, as in:

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?

You can easily work out the more suitable solution to your case changing the Addrinfo methods used to filter the required interface address.

查看更多
Melony?
4楼-- · 2019-01-03 09:27

Similar to the answer using hostname, using the external uname command on UNIX/LINUX:

hostname = `uname -n`.chomp.sub(/\..*/,'')  # stripping off "\n" and the network name if present

for the IP addresses in use (your machine could have multiple network interfaces), you could use something like this:

 # on a Mac:
 ip_addresses = `ifconfig | grep 'inet ' | grep -v 127.0.0.1 | cut -d' ' -f 2`.split
 => ['10.2.21.122','10.8.122.12']

 # on Linux:
 ip_addresses = `ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d':' -f 2 | cut -d' ' -f 1`.split
 => ['10.2.21.122','10.8.122.12']
查看更多
Summer. ? 凉城
5楼-- · 2019-01-03 09:34

Simplest is host_with_port in controller.rb

host_port= request.host_with_port
查看更多
萌系小妹纸
6楼-- · 2019-01-03 09:36

Try this:

host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host               # Output the hostname
查看更多
冷血范
7楼-- · 2019-01-03 09:38

Put the highlighted part in backticks:

`dig #{request.host} +short`.strip # dig gives a newline at the end

Or just request.host if you don't care whether it's an IP or not.

查看更多
登录 后发表回答