83

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

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

[以下] 代码不会建立连接或发送任何数据包(到 64.233.187.99,即 google)。由于 UDP 是一个无状态协议,connect() 仅进行一个系统调用,它会根据地址以及它应该绑定到的接口(以及 IP 地址)来确定如何路由数据包。addr() 返回一个数组,其中包含套接字的族(AF_INET)、本地端口和本地地址(这是我们想要的)。

4

12 回答 12

141

主机名

在 Ruby 中获取主机名的一种简单方法是:

require 'socket'
hostname = Socket.gethostname

问题在于,这依赖于主机知道自己的名称,因为它使用gethostnameoruname系统调用,因此它不适用于原始问题。

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


IP地址

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

require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
于 2009-10-08T04:00:29.610 回答
51

来自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"
于 2008-09-04T00:37:30.987 回答
25

试试这个:

host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host               # Output the hostname
于 2008-09-03T21:19:16.547 回答
13

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

由于这里的所有答案都针对这个简单的场景,因此更简洁的方法是向 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 方法。

于 2011-10-18T14:39:26.450 回答
10

最简单的是host_with_port在controller.rb

host_port= request.host_with_port
于 2010-07-14T13:54:09.850 回答
9

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

require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
于 2011-02-17T14:23:31.130 回答
3

类似于 using 的答案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']
于 2012-09-28T02:45:36.040 回答
2

将突出显示的部分放在反引号中:

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

或者只是request.host如果您不在乎它是否是IP。

于 2009-10-25T02:46:38.023 回答
2

接受的答案有效,但您必须为每个请求创建一个套接字,如果服务器位于本地网络上和/或未连接到 Internet,则它不起作用。我相信下面的内容将始终有效,因为它正在解析请求标头。

request.env["SERVER_ADDR"]
于 2011-01-18T16:16:32.727 回答
1

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

另一种选择是使用WhatIsMyIp.com之类的查找服务。这些家伙会将您的真实 IP 地址返还给您。如果您愿意,这也是您可以在本地服务器上使用 Perl 脚本轻松设置的内容。我相信从 %ENV 输出远程 IP 的 3 行左右的代码应该涵盖你。

于 2008-09-03T22:18:45.140 回答
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 一样可靠。

于 2011-11-17T21:23:16.280 回答
0

尝试:Request.remote_ip

远程IP()

确定原始 IP 地址。REMOTE_ADDR 是标准的,但如果用户在代理后面会失败。HTTP_CLIENT_IP 和/或 HTTP_X_FORWARDED_FOR 由代理设置,因此如果 REMOTE_ADDR 是代理,请检查这些。HTTP_X_FORWARDED_FOR 在多个链式代理的情况下可能是一个逗号分隔的列表;最后一个不受信任的地址是原始 IP。

更新:糟糕,对不起,我误读了文档。

于 2008-09-03T21:06:22.787 回答