2008-09-03 244 views
73

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

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

的[下面]代码不会使 连接或发送任何数据包(以 64.233.187.99这是谷歌)。由于UDP是一种无状态协议,因此连接()仅仅根据地址以及接口(因此IP地址) 将如何路由包 应该绑定到的系统调用。 addr()返回一个包含系列(AF_INET), 本地端口和本地地址(其中 是我们想要的)套接字的 数组。

回答

45

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" 
+0

非常感谢!这工作完全适合我:-) – 2010-06-23 21:13:17

+1

@TopherFangio这是IP 64.233.187.99? – 2013-06-21 06:16:30

+1

@ user422543通过上述问题的编辑,IP地址属于Google。 – 2013-06-22 18:26:01

0

尝试:Request.remote_ip

remote_ip()

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

更新: 糟糕,抱歉,我误读了文档。

+0

这给你一个用户向Rails应用发出请求的IP地址,而不是运行Rails应用的机器的IP地址。 – jsears 2015-12-03 15:39:43

22

试试这个:

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

我喜欢Socket.gethostname的纯度,但对于一个简单的查找系统,你知道`hostname`会起作用,你不能为了简单而打败它 – 2011-07-25 21:55:08

+0

你也可以做`uname -n`.sub( /\..*/,'') – Tilo 2012-09-28 02:44:22

1

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

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

+0

如果没有外部互联网访问,WhatIsMyIP.com将无法使用。 – 2014-12-03 17:34:39

124

主机名

一个简单的方法是拿到主机名在Ruby是:

美中不足的是,这依赖于主机上知道它自己的名字,因为它使用系统调用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 
2

把突出部分在反引号:

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

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

2

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

request.env["SERVER_ADDR"] 
9

此处使用的IP地址是Google的,但您可以使用任何可访问的IP。

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

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

由于所有的答案,在这里用这个简单的情景应对,更清洁的方法是问插槽当前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中的方法。

1
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一样稳定。

2

使用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'] 
相关问题