2008-09-03 12 views
73

Estoy en el proceso de mantener una aplicación de Ruby on Rails y estoy buscando una manera fácil de encontrar el nombre de host o la dirección IP de la casilla en la que estoy (ya que es VM y nuevas instancias pueden tener diferentes nombres de host o direcciones IP). ¿Hay alguna manera rápida y fácil de hacer esto en Ruby on Rails?Obteniendo el nombre de host o IP en Ruby on Rails

Editar: La respuesta a continuación es correcta, pero la aclaración Craig siempre es útil (véase también proporcionado eslabón de respuesta):

El [abajo] Código no hacen una conexión o enviar cualquier paquete (a 64.233.187.99 que es google). Como UDP es un protocolo sin estado, connect() simplemente realiza una llamada al sistema que averigua cómo enrutar los paquetes en función de la dirección y la interfaz (y, por lo tanto, la dirección IP) a la que debe enlazarse. addr() devuelve una matriz que contiene la familia (AF_INET), el puerto local y la dirección local (que es lo que queremos) del socket.

Respuesta

45

De 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

¡Muchas gracias! Esto funcionó perfectamente para mí :-) –

+1

@TopherFangio que es este IP 64.233.187.99? –

+1

@ user422543 Según la edición en la pregunta anterior, la dirección IP pertenece a Google. –

0

intento: Request.remote_ip

remote_ip()

Determine dirección IP de origen. REMOTE_ADDR es el estándar pero fallará si el usuario está detrás de un proxy. HTTP_CLIENT_IP y/o HTTP_X_FORWARDED_FOR se establecen por proxies, así que compruebe si REMOTE_ADDR es un proxy. HTTP_X_FORWARDED_FOR puede ser una lista delimitada por comas en el caso de múltiples proxies encadenados; la última dirección en la que no se confía es la IP de origen.

Actualización: Vaya, lo siento, leí la documentación.

+0

Esto le proporciona la dirección IP de un usuario que emite una solicitud a la aplicación Rails, no la dirección IP de la máquina que ejecuta la aplicación Rails. – jsears

22

Prueba esto:

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

Me gusta Socket.gethostname por la pureza, pero para una simple búsqueda en un sistema donde sabes que 'hostname' va a funcionar, no puedes superarlo por simplicidad –

+0

también puedes hacer' uname -n'.sub (/\..*/, '') – Tilo

1

es probable que notar que tiene varias direcciones IP en cada máquina (127.0.0.1, 192.168.0.1, etc.). Si está utilizando * NIX como su sistema operativo, le sugiero que use hostname, y luego ejecute un DNS para buscar eso. Debería poder usar/etc/hosts para definir el nombre de host local para resolver la dirección IP de esa máquina. Hay una funcionalidad similar en Windows, pero no la he usado desde que Windows 95 fue la punta de lanza.

La otra opción sería presionar un servicio de búsqueda como WhatIsMyIp.com. Estos chicos le devolverán la dirección IP del mundo real. Esto también es algo que puede configurar fácilmente con una secuencia de comandos Perl en un servidor local, si lo prefiere. Creo que 3 líneas más o menos de código para generar la IP remota desde% ENV deberían cubrirlo.

+0

WhatIsMyIP.com no funcionará si no hay acceso externo a Internet. –

124

nombre de host

Una forma sencilla de obtener sólo el nombre de host en Ruby es:

El problema es que esto se basa en el host saber su propio nombre porque utiliza la llamada al sistema gethostname o uname, por lo que No funcionaré para el problema original.

Funcionalmente esto es idéntico a la respuesta hostname, sin invocar un programa externo. El nombre de host puede o no estar completamente calificado, dependiendo de la configuración de la máquina.


dirección IP

Desde Ruby 1.9, también puede utilizar la biblioteca de socket para obtener una lista de las direcciones locales. ip_address_list devuelve una matriz de objetos AddrInfo. ¿Cómo elegir entre eso dependerá de lo que quiere hacer y la cantidad de interfaces que tiene, pero aquí hay un ejemplo que simplemente selecciona el primer no-loopback dirección IPv4 IP como una cadena:

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

Socket.gethostname no siempre devuelve el FQDN. El uso de 'hostname' .strip puede ser más confiable si se desea el FQDN. –

+0

Zócalo. gethostname aparentemente no siempre es estable, vea los comentarios http://stackoverflow.com/q/14112955/32453 – rogerdpack

2

poner la parte resaltada entre comillas sencillas:

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

o simplemente request.host si no le importa si se trata de una IP o no.

7

más simple es host_with_port en controller.rb

host_port= request.host_with_port 
+1

Lo malo es que tiene que estar en el controlador para acceder a la solicitud ... ¡pero es una buena idea! – Tilo

+0

Parece que las otras respuestas son solo hacks, mientras que esto lo hace de la manera correcta. ¿Por qué está enterrado debajo de ellos? – tbodt

2

Las obras respuesta aceptada, pero hay que crear un socket para cada petición y no funciona si el servidor está en una red local y/o no está conectado a la Internet. A continuación, creo que siempre funcionará, ya que está analizando el encabezado de la solicitud.

request.env["SERVER_ADDR"] 
+3

El OP no dijo realmente que tenían acceso al objeto de solicitud en el punto donde necesita la dirección IP. Las soluciones basadas en Socket son más genéricas –

9

Esta dirección de IP utilizada aquí es de Google, pero puede usar cualquier IP accesible.

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

Un servidor generalmente tiene más de una interfaz, al menos una privada y una pública.

Puesto que todas las respuestas aquí frente a este escenario simple, una forma más limpia es preguntar zócalo de la corriente ip_address_list() como en:

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 

Ambos devuelven un objeto addrinfo, así que si necesitas una cadena Puede utilizar el método ip_address(), como en:

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil? 

Se puede trabajar fácilmente la solución más adecuada a su caso el cambio de los métodos utilizados para filtrar addrinfo la dirección de la interfaz requerida.

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

Las dos respuestas con require 'socket' se ven bien. Los que tienen request.blah_blah_blah asumen que está utilizando Rails.

IO debería estar disponible todo el tiempo. El único problema con esta secuencia de comandos sería que si ifconfig se imprime en un feudo diferente en sus sistemas, entonces obtendría resultados diferentes para la IP. La búsqueda del nombre de host debe ser sólida como Sears.

2

Similar a la respuesta usando hostname, utilizando el comando externo uname en UNIX/LINUX:

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

para las direcciones IP en uso (la máquina puede tener varias interfaces de red), usted podría utilizar algo como esto:

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