在 RubyonRails 中获取主机名或 IP

我正在维护一个 Ruby on Rails 应用程序,正在寻找一种简单的方法来找到我所在机器的主机名或 IP 地址(因为它是虚拟机,新实例可能有不同的主机名或 IP 地址)。在 RubyonRails 中有没有一种快速而简单的方法来做到这一点?

编辑: 下面的答案是正确的,但克雷格提供的澄清是有用的(参见答案中提供的链接) :

[以下]代码并不构成 连接或发送任何数据包(至 64.233.187.99也就是 google) ,因为 UDP 是一个无状态协议连接() 只是进行一个系统调用 搞清楚如何传送数据包 根据地址和内容 接口(因此是 IP 地址) 它应该绑定到. addr ()返回一个 包含家族(AF _ INET)的数组, 本地端口和本地地址(其中 是我们想要的)的插座。

100369 次浏览

试试: Request.remote _ ip

Remote _ ip ()

确定原始 IP 地址。 REMOTE _ ADDR 是标准,但将 如果用户在代理后面,则会失败 HTTP _ X _ FORWARDED _ FOR 是由代理设置的,所以如果 REMOTE _ ADDR 是一个代理。 HTTP _ X _ FORWARDED _ FOR 可以用逗号分隔 在多个链式代理的情况下,列表; 最后一个地址 是不可信的是原始 IP。

更新: 抱歉,我看错了文件。

试试这个:

host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host               # Output the hostname

您可能会发现自己在每台计算机上有多个 IP 地址(127.0.0.1、192.168.0.1等)。如果使用 * NIX 作为操作系统,我建议使用 hostname,然后运行 DNS 查找。您应该能够使用/etc/hosts 定义本地主机名,以解析该机器的 IP 地址。Windows 上也有类似的功能,但是自从 Windows95是最先进的之后我就没有用过了。

另一种选择是访问像 什么是 MyIp.com这样的查找服务。这些人会把你现实中的 IP 地址反馈给你。如果您愿意,也可以在本地服务器上使用 Perl 脚本轻松地设置这一点。我相信3行左右的代码输出的远程 IP 从% ENV 应该覆盖你。

来自 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"

主机名

在 Ruby 中获得主机名的一个简单方法是:

require 'socket'
hostname = Socket.gethostname

问题在于,这依赖于主机知道自己的名称,因为它使用 gethostnameuname系统调用,所以对于原来的问题不起作用。

在功能上,这与 hostname答案相同,不需要调用外部程序。主机名可能是完全限定的,也可能不是完全限定的,这取决于计算机的配置。


IP 地址

从 Ruby 1.9开始,您还可以使用 Socket 库获取本地地址列表。ip_address_list返回 AddrInfo对象的数组。如何选择取决于你想做什么和你有多少接口,但这里有一个例子,它只是选择第一个非环回的 IPV4 IP 地址作为一个字符串:

require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address

把突出显示的部分放在反勾中:

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

或者只是 request.host,如果你不在乎它是不是一个 IP。

最简单的是 Controler.rb 中的 host_with_port

host_port= request.host_with_port

接受的答案工作,但你必须为每个请求创建一个套接字,它不工作,如果服务器是在一个本地网络和/或没有连接到互联网。下面,我相信将始终工作,因为它是解析请求标头。

request.env["SERVER_ADDR"]

这里使用的 IP 地址是 Google 的,但是你可以使用任何可访问的 IP 地址。

require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}

服务器通常有多个接口,至少有一个私有接口和一个公共接口。

由于这里的所有答案都涉及到这个简单的场景,所以一个更简单的方法是向 Socket 询问当前的 ip_address_list(),如下所示:

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

两者都返回一个 Addrinfo 对象,因此如果需要字符串,可以使用 ip_address()方法,如下所示:

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?

您可以很容易地找到更适合您的情况的解决方案,更改用于过滤所需接口地址的 Addrinfo 方法。

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}\ /)

require 'socket'回答的几个问题看起来不错 假设您正在使用 Rails。

IO 应该一直可用。这个脚本的唯一问题是,如果 ifconfig在您的系统上输出在不同的庄园中,那么您将得到不同的 IP 结果。查找主机名应该像西尔斯一样可靠。

与使用 hostname得到的答案类似,在 UNIX/LINUX 上使用外部 uname命令:

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

对于正在使用的 IP 地址(您的计算机可能有多个网络接口) , 你可以用这样的东西:

 # 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']