2008-09-03 12 views
73

Ich bin dabei, eine Ruby on Rails-App zu verwalten und suche nach einer einfachen Möglichkeit, den Hostnamen oder die IP-Adresse der Box zu finden, in der ich gerade bin VM und neue Instanzen können unterschiedliche Hostnamen oder IP-Adressen haben). Gibt es eine schnelle und einfache Möglichkeit, dies in Ruby on Rails zu tun?Abrufen des Hostnamens oder der IP-Adresse in Ruby on Rails

Edit: Die Antwort unten korrekt ist, aber die Klärung Craig vorgesehen ist nützlich (siehe auch in der Antwort angegebenen Link):

Die [unten] Code nicht eine Verbindung herstellen oder Pakete senden (an 64.233.187.99 das ist google). Da UDP ein statusloses Protokoll ist, führt connect() lediglich einen Systemaufruf aus, der herausfindet, wie die Pakete basierend auf der Adresse und welcher Schnittstelle (und somit IP-Adresse) an sie gebunden werden sollen. addr() gibt ein Array zurück, das die Familie (AF_INET), den lokalen Port und die lokale Adresse (die ist, was wir wollen) des Sockets enthält.

Antwort

45

Von 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

Vielen Dank! Das funktionierte perfekt für mich :-) –

+1

@TopherFangio was ist das für IP 64.233.187.99? –

+1

@ user422543 Nach dem Bearbeiten in der obigen Frage gehört die IP-Adresse zu Google. –

0

Versuch: Request.remote_ip

remote_ip()

Ursprung Bestimmen Sie die IP-Adresse. REMOTE_ADDR ist der Standard, aber schlägt fehl, wenn der Benutzer hinter einem Proxy ist. HTTP_CLIENT_IP und/oder HTTP_X_FORWARDED_FOR werden durch Proxies gesetzt, also prüfen Sie diese, wenn REMOTE_ADDR ein Proxy ist. HTTP_X_FORWARDED_FOR kann bei mehrfach verketteten Proxies eine Liste mit Kommas sein; Die letzte Adresse, die nicht vertrauenswürdig ist, ist die ursprüngliche IP.

Update: Hoppla, tut mir leid, ich habe die Dokumentation falsch gelesen.

+0

Hier erhalten Sie die IP-Adresse eines Benutzers, der eine Anfrage an die Rails-App sendet, nicht die IP-Adresse des Computers, auf dem die Rails-App läuft. – jsears

22

Versuchen Sie folgendes:

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

Ich mag Socket.Gethostname für die Reinheit, aber für eine einfache Suche auf einem System, wo Sie wissen, 'Hostname' wird funktionieren, Sie können es nicht für die Einfachheit schlagen –

+0

Sie könnten auch' uname -n' (/\..*/, '') – Tilo

1

Sie werden sich wahrscheinlich mehrere IP-Adressen auf jedem Rechner (127.0.0.1, 192.168.0.1, usw.) zu finden ist. Wenn Sie * NIX als Ihr Betriebssystem verwenden, würde ich vorschlagen, hostname zu verwenden, und dann eine DNS-Suche nach diesem auszuführen. Sie sollten/etc/hosts verwenden können, um den lokalen Hostnamen für die Auflösung der IP-Adresse für diesen Computer zu definieren. Es gibt eine ähnliche Funktionalität unter Windows, aber ich habe sie nicht verwendet, seit Windows 95 war die blutigste Kante. Die andere Option wäre ein Suchdienst wie WhatIsMyIp.com zu treffen. Diese Leute werden dir deine IP-Adresse zurückgeben. Dies ist auch etwas, das Sie einfach mit einem Perl-Skript auf einem lokalen Server einrichten können, wenn Sie dies bevorzugen. Ich glaube, 3 Zeilen oder so Code, um die Remote-IP von% ENV auszugeben, sollten Sie abdecken.

+0

WhatIsMyIP.com funktioniert nicht, wenn es keinen externen Internetzugang gibt. –

124

Hostname

Eine einfache Möglichkeit, nur den Hostnamen in Ruby zu bekommen ist:

Der Haken dabei ist, dass diese auf dem Host verlässt sich zu wissen einen eigenen Namen, weil es entweder gethostname oder uname Systemaufruf verwendet, so dass es wi Ich arbeite nicht für das ursprüngliche Problem.

Funktional ist dies identisch mit der hostname Antwort, ohne ein externes Programm aufzurufen. Der Hostname ist je nach Konfiguration des Rechners möglicherweise nicht vollständig qualifiziert.


IP-Adresse

Da Ruby 1.9 können Sie auch die Socket-Bibliothek verwenden, um eine Liste der lokalen Adressen zu erhalten. ip_address_list gibt ein Array von AddrInfo Objekten zurück. Wie Sie wählen es hängt davon ab, was Sie tun möchten und wie viele Schnittstellen, die Sie haben, aber hier ist ein Beispiel, das einfach als eine Zeichenfolge, die die erste nicht-Loopback IPV4 IP-Adresse wählt:

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

Socket.Gethostname gibt den FQDN nicht immer zurück. Die Verwendung von 'hostname'.strip ist möglicherweise zuverlässiger, wenn der FQDN gewünscht wird. –

+0

Sockel. gethostname ist anscheinend nicht immer stabil, siehe Kommentare http://stackoverflow.com/q/14112955/32453 – rogerdpack

2

Setzen Sie den markierten Teil in Backticks:

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

oder nur request.host, wenn Sie es egal, ob es sich um eine IP oder nicht.

7

Simplest ist host_with_port in controller.rb

host_port= request.host_with_port 
+1

Nachteil ist, dass Sie in der Steuerung sein müssen, um auf die Anfrage zuzugreifen .. aber gute Idee! – Tilo

+0

Es scheint, dass die anderen Antworten nur Hacks sind, während dies der richtige Weg ist. Warum ist es unter ihnen begraben? – tbodt

2

Die akzeptierte Antwort funktioniert, aber Sie haben eine Buchse für jede Anforderung erstellen und es funktioniert nicht, wenn der Server auf einem lokalen Netzwerk ist und/oder nicht verbunden in das Internet. Das unten, glaube ich, wird immer funktionieren, da es den Anforderungsheader analysiert.

+3

Das OP hat nicht wirklich gesagt, dass sie Zugriff auf das Anfrageobjekt an dem Punkt hatten, an dem er die IP-Adresse benötigt. Die Socket-basierten Lösungen sind allgemeiner –

9

Die hier verwendete IP-Adresse ist die von Google, aber Sie können jede zugängliche IP verwenden.

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

Ein Server verfügt normalerweise über mehr als eine Schnittstelle, mindestens eine private und eine öffentliche.

Da alle Antworten hier mit diesem einfachen Szenario beschäftigen, ist ein sauberer Weg Sockel für die aktuellen ip_address_list() wie in fragen:

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 

Sowohl ein addrinfo Objekt zurückgeben, wenn Sie also einen String benötigen, können Sie verwenden Sie die ip_address() Methode, wie in:

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil? 

Sie bequem die geeignetere Lösung für Ihren Fall arbeiten können, die addrinfo Methoden Ändern der erforderlichen Schnittstellenadresse zu filtern.

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}\ /) 

Die paar Antworten mit require 'socket' sehen gut aus. Diejenigen mit request.blah_blah_blah nehmen an, dass Sie Rails verwenden.

IO sollte die ganze Zeit verfügbar sein. Das einzige Problem mit diesem Skript wäre, dass, wenn ifconfig in einem anderen Land auf Ihren Systemen ausgegeben wird, würden Sie unterschiedliche Ergebnisse für die IP erhalten. Der Hostname Look-Up sollte als Sears solid sein.

2

Ähnlich wie die Antwort mit hostname, unter Verwendung des externen uname Befehl unter UNIX/LINUX:

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

für die verwendeten IP-Adressen (Ihr Gerät mehrere Netzwerkschnittstellen haben könnte), Sie so etwas wie verwenden könnte this:

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