Jestem w trakcie utrzymywania aplikacji Ruby on Rails i szukam łatwego sposobu na znalezienie nazwy hosta lub adresu IP skrzynki, w której się znajduję (ponieważ jest to maszyna wirtualna, a nowe instancje mogą mieć różne nazwy hostów lub adresy IP) . Czy istnieje szybki i łatwy sposób na zrobienie tego w Ruby on Rails?
Edycja: poniższa odpowiedź jest prawidłowa, ale wyjaśnienie podane przez Craiga jest przydatne (zobacz również link podany w odpowiedzi):
Kod [poniżej] NIE nawiązuje połączenia ani nie wysyła żadnych pakietów (do 64.233.187.99 czyli google). Ponieważ UDP jest protokołem bezstanowym, connect () po prostu wykonuje wywołanie systemowe, które określa, jak trasować pakiety na podstawie adresu i interfejsu (a tym samym adresu IP), z którym ma się wiązać. addr () zwraca tablicę zawierającą rodzinę (AF_INET), port lokalny i adres lokalny (o co nam chodzi) gniazda.
źródło
Nazwa hosta
Prosty sposób na uzyskanie nazwy hosta w Rubim to:
require 'socket' hostname = Socket.gethostname
Problem polega na tym, że polega to na tym, że host zna swoją nazwę, ponieważ używa wywołania systemowego
gethostname
lubuname
, więc nie będzie działać w przypadku pierwotnego problemu.Funkcjonalnie jest to identyczne z
hostname
odpowiedzią, bez wywoływania programu zewnętrznego. Nazwa hosta może, ale nie musi, być w pełni kwalifikowana, w zależności od konfiguracji komputera.Adres IP
Od wersji Ruby 1.9 możesz również użyć biblioteki Socket, aby uzyskać listę adresów lokalnych.
ip_address_list
zwraca tablicę obiektów AddrInfo . To, jak wybierzesz, będzie zależeć od tego, co chcesz zrobić i ile masz interfejsów, ale oto przykład, który po prostu wybiera pierwszy adres IPV4 bez sprzężenia zwrotnego jako ciąg:require 'socket' ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
źródło
Spróbuj tego:
host = `hostname`.strip # Get the hostname from the shell and removing trailing \n puts host # Output the hostname
źródło
hostname
jedzie do pracy, nie można pokonać go dla uproszczeniauname -n
.sub (/\..*/, '')Serwer zazwyczaj ma więcej niż jeden interfejs, co najmniej jeden prywatny i jeden publiczny.
Ponieważ wszystkie odpowiedzi tutaj dotyczą tego prostego scenariusza, czystszym sposobem jest poproszenie Socket o prąd,
ip_address_list()
jak w: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
Oba zwracają obiekt Addrinfo, więc jeśli potrzebujesz łańcucha, możesz użyć
ip_address()
metody, jak w:ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?
Możesz łatwo znaleźć bardziej odpowiednie rozwiązanie dla swojego przypadku, zmieniając metody Addrinfo używane do filtrowania wymaganego adresu interfejsu.
źródło
Ten użyty tutaj adres IP należy do Google, ale możesz użyć dowolnego dostępnego adresu IP.
require "socket" local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
źródło
Najprostszy jest plik
host_with_port
controller.rbźródło
Zaakceptowana odpowiedź działa, ale musisz utworzyć gniazdo dla każdego żądania i nie działa, jeśli serwer znajduje się w sieci lokalnej i / lub nie jest połączony z Internetem. Poniżej, jak sądzę, zawsze będzie działać, ponieważ analizuje nagłówek żądania.
request.env["SERVER_ADDR"]
źródło
Umieść podświetloną część w grawerach:
`dig #{request.host} +short`.strip # dig gives a newline at the end
Lub po prostu
request.host
nie obchodzi Cię, czy to adres IP, czy nie.źródło
Podobnie jak w przypadku odpowiedzi przy
hostname
użyciuuname
polecenia zewnętrznego w systemie UNIX / LINUX:hostname = `uname -n`.chomp.sub(/\..*/,'') # stripping off "\n" and the network name if present
dla używanych adresów IP (twój komputer może mieć wiele interfejsów sieciowych), możesz użyć czegoś takiego:
# 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']
źródło
Prawdopodobnie będziesz mieć wiele adresów IP na każdym komputerze (127.0.0.1, 192.168.0.1 itd.). Jeśli używasz * NIX jako swojego systemu operacyjnego, sugerowałbym użycie
hostname
, a następnie uruchomienie wyszukiwania DNS. Powinieneś być w stanie użyć / etc / hosts do zdefiniowania lokalnej nazwy hosta, która będzie tłumaczona na adres IP tej maszyny. W systemie Windows jest podobna funkcjonalność, ale nie korzystałem z niej, ponieważ Windows 95 był krwawiącą krawędzią.Inną opcją byłoby skorzystanie z usługi wyszukiwania, takiej jak WhatIsMyIp.com . Ci faceci przekażą Ci Twój prawdziwy adres IP. Jest to również coś, co możesz łatwo skonfigurować za pomocą skryptu Perl na lokalnym serwerze, jeśli wolisz. Uważam, że około 3 wierszy kodu do wyprowadzenia zdalnego adresu IP z% ENV powinno Cię pokryć.
źródło
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}\ /)
Kilka odpowiedzi
require 'socket'
wygląda dobrze. Te z request.blah_blah_blah zakładają, że używasz Railsów.IO powinno być dostępne przez cały czas. Jedyny problem z tym skryptem polegałby na tym, że gdybyś
ifconfig
był wyprowadzany w innej rezydencji w twoim systemie, wtedy otrzymywałbyś różne wyniki dla adresu IP. Nazwa hosta powinna być solidna, jak Sears.źródło
try: Request.remote_ip
Aktualizacja: Ups, przepraszam, że źle przeczytałem dokumentację.
źródło