Abrufen des Hostnamens oder der IP in Ruby on Rails

80

Ich bin gerade dabei, eine Ruby on Rails-App zu warten, und suche nach einer einfachen Möglichkeit, den Hostnamen oder die IP-Adresse der Box zu finden, auf der ich mich befinde (da es sich um eine VM handelt und neue Instanzen möglicherweise andere Hostnamen oder IP-Adressen haben). . Gibt es eine schnelle und einfache Möglichkeit, dies in Ruby on Rails zu tun?

Bearbeiten: Die Antwort unten ist korrekt, aber die Klarstellung, die Craig gegeben hat, ist nützlich (siehe auch den bereitgestellten Link in der Antwort):

Der Code [unten] stellt KEINE Verbindung her und sendet keine Pakete (an 64.233.187.99, was Google ist). Da UDP ein zustandsloses Protokoll ist, führt connect () lediglich einen Systemaufruf durch, der herausfindet, wie die Pakete basierend auf der Adresse weitergeleitet werden und an welche Schnittstelle (und damit IP-Adresse) sie gebunden werden soll. addr () gibt ein Array zurück, das die Familie (AF_INET), den lokalen Port und die lokale Adresse (was wir wollen) des Sockets enthält.

Chris Bunch
quelle

Antworten:

50

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"
titanös
quelle
1
@ user422543 Gemäß der Bearbeitung in der obigen Frage gehört die IP-Adresse Google.
Topher Fangio
137

Hostname

Eine einfache Möglichkeit, den Hostnamen in Ruby abzurufen, ist:

require 'socket'
hostname = Socket.gethostname

Der Haken dabei ist, dass der Host seinen eigenen Namen kennt, da er entweder den Systemaufruf gethostnameoder den unameSystemaufruf verwendet, sodass er für das ursprüngliche Problem nicht funktioniert.

Funktionell ist dies identisch mit der hostnameAntwort, ohne ein externes Programm aufzurufen. Der Hostname kann abhängig von der Konfiguration des Computers vollständig qualifiziert sein oder nicht.


IP Adresse

Seit Ruby 1.9 können Sie auch die Socket-Bibliothek verwenden, um eine Liste der lokalen Adressen abzurufen. Gibtip_address_list ein Array von AddrInfo- Objekten zurück. Wie Sie auswählen, hängt davon ab, was Sie tun möchten und wie viele Schnittstellen Sie haben. Hier ist ein Beispiel, in dem einfach die erste IPV4-IP-Adresse ohne Loopback als Zeichenfolge ausgewählt wird:

require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
Tim Peters
quelle
Socket.gethostname gibt nicht immer den vollqualifizierten Domänennamen zurück. Die Verwendung von 'hostname'.strip ist möglicherweise zuverlässiger, wenn der FQDN gewünscht wird.
Travis Bear
Steckdose. gethostname ist anscheinend nicht immer stabil, siehe Kommentare stackoverflow.com/q/14112955/32453
rogerdpack
Offizielle Dokumentseite: ruby-doc.org/stdlib/libdoc/socket/rdoc/…
HarlemSquirrel
24

Versuche dies:

host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host               # Output the hostname
John Topley
quelle
4
Ich mag Socket.gethostname für die Reinheit, aber für eine einfache Suche auf einem System, von dem Sie wissen hostname, dass es funktionieren wird, können Sie es der Einfachheit halber nicht übertreffen
Dave Smylie
Sie könnten auch uname -n.sub (/\..*/, '')
Tilo
12

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

Da sich alle Antworten hier mit diesem einfachen Szenario befassen, besteht eine sauberere Möglichkeit darin, Socket nach dem aktuellen ip_address_list()Stand zu fragen, wie in:

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

Beide geben ein Addrinfo-Objekt zurück. Wenn Sie also eine Zeichenfolge benötigen, können Sie die ip_address()Methode wie folgt verwenden :

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?

Sie können leicht die geeignetere Lösung für Ihren Fall finden, indem Sie die Addrinfo-Methoden ändern, mit denen die erforderliche Schnittstellenadresse gefiltert wird.

Claudio Floreani
quelle
9

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

require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
DD-Doug
quelle
8

Am einfachsten ist host_with_portin controller.rb

host_port= request.host_with_port
Salil
quelle
2
Nachteil ist, dass Sie in der Steuerung sein müssen, um auf die Anfrage zuzugreifen .. aber gute Idee!
Tilo
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 müssen für jede Anfrage einen Socket erstellen. Dies funktioniert nicht, wenn sich der Server in einem lokalen Netzwerk befindet und / oder nicht mit dem Internet verbunden ist. Ich glaube, dass das Folgende immer funktioniert, da es den Anforderungsheader analysiert.

request.env["SERVER_ADDR"]
Hacintosh
quelle
3
Das OP hat nicht gesagt, dass sie an dem Punkt, an dem er die IP-Adresse benötigt, Zugriff auf das Anforderungsobjekt hatten. Die Socket-basierten Lösungen sind allgemeiner
Chris McCauley
2

Fügen Sie den hervorgehobenen Teil in Backticks ein:

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

Oder nur, request.hostwenn es Ihnen egal ist, ob es sich um eine IP handelt oder nicht.

Sai
quelle
2

Ähnlich wie bei der Antwort mit hostnamedem externen unameBefehl unter UNIX / LINUX:

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

Für die verwendeten IP-Adressen (Ihr Computer kann mehrere Netzwerkschnittstellen haben) können Sie Folgendes verwenden:

 # 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']
Tilo
quelle
1

Sie werden wahrscheinlich feststellen, dass auf jedem Computer mehrere IP-Adressen vorhanden sind (127.0.0.1, 192.168.0.1 usw.). Wenn Sie * NIX als Betriebssystem verwenden, würde ich empfehlen hostname, einen DNS-Lookup zu verwenden und dann auszuführen. Sie sollten in der Lage sein, mit / etc / hosts den lokalen Hostnamen zu definieren, der in die IP-Adresse für diesen Computer aufgelöst werden soll. Es gibt ähnliche Funktionen unter Windows, aber ich habe sie nicht verwendet, da Windows 95 die neueste Version war.

Die andere Möglichkeit wäre, einen Suchdienst wie WhatIsMyIp.com aufzurufen . Diese Jungs werden Ihnen Ihre reale IP-Adresse zurückgeben. Dies können Sie auch einfach mit einem Perl-Skript auf einem lokalen Server einrichten, wenn Sie dies bevorzugen. Ich glaube, dass ungefähr 3 Codezeilen zur Ausgabe der Remote-IP von% ENV Sie abdecken sollten.

Jack M.
quelle
WhatIsMyIP.com funktioniert nicht, wenn kein externer Internetzugang vorhanden ist.
der Blechmann
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 gehen davon aus, dass Sie Rails verwenden.

IO sollte jederzeit verfügbar sein. Das einzige Problem mit diesem Skript wäre, dass ifconfigSie unterschiedliche Ergebnisse für die IP erhalten , wenn es auf Ihren Systemen in einem anderen Manor ausgegeben wird. Die Suche nach dem Hostnamen sollte fest wie Sears sein.

Kevin Krauss
quelle
0

versuchen Sie: Request.remote_ip

remote_ip ()

Bestimmen Sie die ursprüngliche IP-Adresse. REMOTE_ADDR ist der Standard, schlägt jedoch fehl, wenn sich der Benutzer hinter einem Proxy befindet. HTTP_CLIENT_IP und / oder HTTP_X_FORWARDED_FOR werden von Proxys festgelegt. Überprüfen Sie daher, ob REMOTE_ADDR ein Proxy ist. HTTP_X_FORWARDED_FOR kann bei mehreren verketteten Proxys eine durch Kommas getrennte Liste sein. Die letzte Adresse, der nicht vertraut wird, ist die Ursprungs-IP.

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

Craig
quelle
Dies gibt Ihnen die IP-Adresse eines Benutzers an, der eine Anfrage an die Rails-App sendet, nicht die IP-Adresse des Computers, auf dem die Rails-App ausgeführt wird.
jsears