在Ruby on Rails中获取主机名或IP

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

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

下面的代码不会build立连接或发送任何数据包(到64.233.187.99这是谷歌)。 由于UDP是一个无状态协议,connect()只是进行一个系统调用,它根据地址和应该绑定的接口(以及IP地址)计算出如何路由数据包。 addr()返回一个包含系列(AF_INET),本地端口和本地地址(这是我们想要的)套接字的数组。

来自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系统调用,所以它不会工作原来的问题。

从function上讲,这与hostname答案相同,不需要调用外部程序。 主机名称可能是也可能不是完全合格的,具体取决于机器的configuration。


IP地址

从Ruby 1.9开始,你也可以使用Socket库来获取本地地址列表。 ip_address_list返回一个AddrInfo对象的数组。 你如何select它取决于你想要做什么以及你有多less个接口,但是这里有一个例子,它简单地select第一个非回送IPV4 IP地址作为string:

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

尝试这个:

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

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

由于这里所有的答案处理这个简单的情况,更简洁的方法是向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对象,所以如果你需要一个string,你可以使用ip_address()方法,如下所示:

 ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil? 

你可以很容易地find更适合你的情况的解决scheme,改变用于过滤所需接口地址的Addrinfo方法。

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

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

最简单的是host_with_port中的host_with_port

 host_port= request.host_with_port 

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

 request.env["SERVER_ADDR"] 

把突出显示的部分反引号:

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

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

与使用hostname的答案类似,在UNIX / LINUX上使用external uname命令:

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

对于正在使用的IP地址(您的机器可能有多个networking接口),您可以使用如下所示:

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

您可能会发现自己在每台计算机上都有多个IP地址(127.0.0.1,192.168.0.1等)。 如果您使用* NIX作为您的操作系统,我会build议使用hostname ,然后运行一个DNS查找。 您应该能够使用/ etc / hosts来定义本地主机名称以parsing为该机器的IP地址。 在Windows上也有类似的function,但是自从Windows 95出现以来,我一直没有使用它。

另一种select是像WhatIsMyIp.com这样的查找服务。 这些家伙会把你的真实IP地址反馈给你。 如果您愿意,也可以使用本地服务器上的Perl脚本轻松设置。 我相信3行左右的代码输出来自%ENV的远程IP应该会覆盖你。

 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'的几个答案看起来不错。 与request.blah_blah_blah的那些假设你正在使用Rails。

IO应该始终可用。 这个脚本的唯一问题是,如果ifconfig在系统上以不同的方式输出,那么你将得到不同的IP结果。 主机名查找应该像Sears一样稳定。

尝试: Request.remote_ip

remote_ip()

确定始发IP地址。 REMOTE_ADDR是标准的,但如果用户在代理之后,将会失败。 HTTP_CLIENT_IP和/或HTTP_X_FORWARDED_FOR由代理设置,因此如果REMOTE_ADDR是代理,请检查这些代理。 对于多个链接的代理,HTTP_X_FORWARDED_FOR可能是逗号分隔的列表; 最后一个不可信的地址是发起IP。

更新:哎呀,对不起,我误解了文档。