Pergunta

Estou no processo de manutenção de um aplicativo Ruby on Rails e estou procurando uma maneira fácil de encontrar o nome do host ou endereço IP da caixa em que estou (já que é uma VM e novas instâncias podem ter nomes de host ou endereços IP diferentes) .Existe uma maneira rápida e fácil de fazer isso em Ruby on Rails?

Editar:A resposta abaixo está correta, mas o esclarecimento fornecido por Craig é útil (veja também o link fornecido na resposta):

O código [abaixo] não faz uma conexão ou envia nenhum pacotes (para 64.233.187.99, que é o Google).Como o UDP é um protocolo apátrida Connect () apenas faz uma chamada de sistema que descobre como rotear os pacotes com base no endereço e a qual interface (e, portanto, o endereço IP) para o qual deve se ligar.addr () retorna uma matriz que contém a família (af_inet), porta local e endereço local (que é o que queremos) do soquete.

Foi útil?

Solução

De coderr.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"

Outras dicas

nome de anfitrião

Uma maneira simples de obter o nome do host em Ruby é:

require 'socket'
hostname = Socket.gethostname

O problema é que isso depende do host saber seu próprio nome porque ele usa o gethostname ou uname chamada de sistema, portanto não funcionará para o problema original.

Funcionalmente isto é idêntico ao hostname responder, sem invocar um programa externo.O nome do host pode ou não ser totalmente qualificado, dependendo da configuração da máquina.


Endereço de IP

Desde o Ruby 1.9, você também pode usar a biblioteca Socket para obter uma lista de endereços locais. ip_address_list retorna uma matriz de AddrInfo objetos.A escolha dependerá do que você deseja fazer e de quantas interfaces você possui, mas aqui está um exemplo que simplesmente seleciona o primeiro endereço IP IPV4 sem loopback como uma string:

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

Experimente isto:

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

Um servidor normalmente possui mais de uma interface, pelo menos uma privada e uma pública.

Como todas as respostas aqui tratam desse cenário simples, uma maneira mais limpa é perguntar ao Socket o valor atual ip_address_list() como em:

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 retornam um objeto Addrinfo, então se você precisar de uma string você pode usar o ip_address() método, como em:

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?

Você pode facilmente encontrar a solução mais adequada para o seu caso, alterando os métodos Addrinfo usados ​​para filtrar o endereço da interface necessária.

Este endereço IP usado aqui é do Google, mas você pode usar qualquer IP acessível.

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

O mais simples é host_with_port em controlador.rb

host_port= request.host_with_port

A resposta aceita funciona, mas você precisa criar um soquete para cada solicitação e não funciona se o servidor estiver em uma rede local e/ou não conectado à internet.Acredito que o procedimento abaixo sempre funcionará, pois está analisando o cabeçalho da solicitação.

request.env["SERVER_ADDR"]

Coloque a parte destacada entre crases:

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

Ou apenas request.host se você não se importa se é um IP ou não.

Semelhante à resposta usando hostname, usando o externo uname comando no UNIX/LINUX:

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

Para os endereços IP em uso (sua máquina pode ter várias interfaces de rede), você pode usar algo assim:

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

Você provavelmente terá vários endereços IP em cada máquina (127.0.0.1, 192.168.0.1, etc.).Se você estiver usando *NIX como sistema operacional, sugiro usar hostname, e, em seguida, executar uma pesquisa de DNS sobre isso.Você deve ser capaz de usar /etc/hosts para definir o nome do host local para resolver o endereço IP dessa máquina.Existe uma funcionalidade semelhante no Windows, mas não a uso desde que o Windows 95 era o que há de mais moderno.

A outra opção seria acessar um serviço de pesquisa como WhatIsMyIp.com.Esses caras devolverão seu endereço IP do mundo real para você.Isso também é algo que você pode configurar facilmente com um script Perl em um servidor local, se preferir.Acredito que cerca de 3 linhas de código para gerar o IP remoto de% ENV devem cobrir você.

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

O par de respostas com require 'socket' parece bom.Aqueles com request.blah_blah_blah assumem que você está usando trilhos.

IO deve estar disponível o tempo todo.O único problema com este script seria que se ifconfig for gerado de uma maneira diferente em seus sistemas, você obterá resultados diferentes para o IP.A pesquisa do nome do host deve ser sólida como Sears.

tentar: Solicitação.remote_ip

ip_remoto()

Determine o endereço IP de origem.Remote_addr é o padrão, mas falhará se o usuário estiver por trás de um proxy.Http_client_ip e/ou http_x_forwarded_for são definidos por proxies, portanto, verifique se REMOTE_ADDR for um proxy.Http_x_forwarded_for pode ser uma lista delimitada por vírgula no caso de vários proxies encadeados;O último endereço que não é confiável é o IP de origem.

Atualizar:Ops, desculpe, eu interpretei mal a documentação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top