Obter o nome da máquina ou o IP em Ruby nos carris
Estou no processo de manter um aplicativo Ruby on Rails e estou procurando uma maneira fácil de encontrar o nome ou endereço IP da caixa em que estou (uma vez que é um VM e novas instâncias podem ter diferentes nomes de host ou endereços IP). Existe uma maneira rápida e fácil de fazer isso em Ruby on Rails?
editar: a resposta abaixo está correcta, mas o esclarecimento que Craig forneceu é útil (Ver também a ligação fornecida na resposta):
o código [abaixo] não faz um ligação ou envio pacotes (para 64.233.187.99 que é o google). Uma vez que UDP é uma conexão de Protocolo apátrida() apenas faz uma chamada de sistema que descobre como encaminhar os pacotes baseado no endereço e no que interface (e, portanto, endereço IP) deve ligar-se a isso. o addr () devolve um lista que contém a família (AF_INET), porto local e endereço local (que é o que queremos) do socket.
12 answers
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"
Nome da máquina
Uma maneira simples de obter o nome da máquina em Ruby é:
require 'socket'
hostname = Socket.gethostname
A captura é que isto depende do host saber o seu próprio nome porque ele usa a chamada do sistema {[[2]} ou uname
, por isso não vai funcionar para o problema original.
hostname
, sem invocar um programa externo. O nome da máquina pode ou não ser totalmente qualificado, dependendo da configuração da máquina.
IP Endereço
Desde o ruby 1.9, você também pode usar a Biblioteca Socket para obter uma lista de endereços locais. ip_address_list
devolve uma lista de objectos AddrInfo . A forma como você escolhe dele dependerá do que você deseja fazer e de quantas interfaces você tem, mas aqui está um exemplo que simplesmente seleciona o primeiro endereço IP não-loopback IPV4 como um texto:
require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
Tenta isto:
host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host # Output the hostname
Um servidor normalmente tem mais de uma interface, pelo menos uma privada e uma pública.
Uma vez que todas as respostas aqui lidam com este cenário simples, uma maneira mais limpa é pedir ao Socket a actual {[[2]} 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 devolvem um objecto Addrinfo, por isso, se precisar de um texto, pode usar o método ip_address()
, como em:
ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?
Você pode facilmente resolver a solução mais adequada para o seu caso, alterando os métodos Addrinfo usados para filtrar a interface necessária endereco.
Este endereço IP aqui usado é 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
no comando.rb
host_port= request.host_with_port
A resposta aceita funciona mas você tem que criar um socket para cada pedido e não funciona se o servidor está em uma rede local e/ou não conectado à internet. O abaixo, eu acredito que sempre funcionará uma vez que está processando o cabeçalho do pedido.
request.env["SERVER_ADDR"]
Coloque a parte destacada em retoques:
`dig #{request.host} +short`.strip # dig gives a newline at the end
Ou apenas request.host
Se não te importas se é um IP ou não.
Semelhante à resposta usando hostname
, usando o comando externo uname
no UNIX / LINUX:
hostname = `uname -n`.chomp.sub(/\..*/,'') # stripping off "\n" and the network name if present
Para os endereços IP em uso (a sua máquina pode ter várias interfaces de rede), dava-te jeito 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']
É provável que tenha vários endereços IP em cada máquina (127.0. 0. 1, 192. 168. 0. 1, etc.). Se está a usar o *NIX como seu SO, eu sugiro o uso de {[[0]}, e depois fazer uma pesquisa DNS sobre isso. Você deve ser capaz de USAR /etc/hosts para definir o nome da máquina local para resolver para 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 limite de hemorragia.
A outra opção seria aceder a um serviço de pesquisa. tipo WhatIsMyIp.com estes tipos devolvem-te o teu endereço de IP do mundo real. Isto também é algo que você pode facilmente configurar com um script Perl em um servidor local, se preferir. Acredito que 3 linhas de código para enviar 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 bem. Aqueles com pedido.blah_blah_blah
assume que estás a usar Carris.
Deve estar sempre disponível. O único problema com este script seria que se ifconfig
é a saída em um solar diferente em seus sistemas, então você obteria resultados diferentes para o IP. A aparência do nome da máquina deverá ser sólida como Sears.
Tentar: Pedido.remote_ip
Remote_ip ()
Determinar o endereço IP de origem. O REMOTE_ADDR é o padrão, mas irá falha se o usuário estiver por trás de um proxy. HTTP_ CLIENT_ IP e/ou HTTP_ x_ FORWARDED_ for are set by proxies so check for these if REMOTE_ADDR é um proxy. HTTP_X_FORWARDED_FOR pode ser uma vírgula delimitada lista no caso de vários proxies acorrentados; o último endereço que não é confiável é a origem PI.
Actualizar: Desculpa ter lido mal a documentação.