2008-09-03 466 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'] 
相關問題