Ruby: 获取本地IP地址(Unix系统)

15

我需要获取我的IP地址(即动态主机配置协议(DHCP)获得的地址)。我在environment.rb文件中使用以下代码:

LOCAL_IP = `ifconfig wlan0`.match(/inet addr:(\d*\.\d*\.\d*\.\d*)/)[1] || "localhost"

但是否有更优雅或更简洁的 Ruby 解决方案呢?


可能存在多个本地IP地址。通常,要使用的地址(例如打开监听套接字)是通过配置文件指定的。 - Thomas
我需要 wlan0 的 inet 地址。我通过 DHCP 从我的 wifi 路由器获取它。因此,对于我的开发环境,每次重新连接到路由器时都需要设置新的 IP。所以现在我想要从系统自动获取它。我使用 Unix 命令来获取它,它可以正常工作,但现在我正在寻找更多 Ruby 方式的解决方案。 - fl00r
可能重复:https://dev59.com/03VD5IYBdhLWcg3wO5ED - steenslag
是的,这是重复内容。但我无法删除它。 - fl00r
3个回答

31

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

由于所有这里的答案都处理了这个简单的情况,更清晰的方式是像下面这样通过 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方法来过滤所需的接口地址,从而轻松找到更适合您情况的解决方案。


3
顺便提一下,我认为在v1.8中这个不可用。 - nhed
为了完整性,获取IP地址的代码如下:Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.getnameinfo[0] - Henley
作为一条注释,ip_address_list是在1.9.x中引入的。 - rogerdpack

11
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 #google
    s.addr.last
  end
ensure
  Socket.do_not_reverse_lookup = orig
end

puts local_ip

这里找到。


如果机器所在的局域网没有连接到广域网,那么这种方法会崩溃。我在这种情况下遇到了崩溃问题。 - qichunren

7
这是对steenslag解决方案的小修改。
require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}

3
为什么这是一种改进?@steenslag将更快地运行,因为它禁用了DNS查询,代码越短并不总是越好。 - nhed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接