Получение имени хоста или IP в Ruby on Rails
Я нахожусь в процессе обслуживания приложения Ruby on Rails и ищу простой способ найти имя хоста или IP-адрес ящика, на котором я работаю (так как это виртуальная машина и новые экземпляры могут иметь разные имена хостов или IP-адреса), Есть ли быстрый и простой способ сделать это в Ruby on Rails?
Изменить: Ответ ниже является правильным, но предоставленное Крейгом разъяснение полезно (см. Также предоставленную ссылку в ответе):
Код [ниже] НЕ устанавливает соединение и не отправляет какие-либо пакеты (на 64.233.187.99, который является Google). Поскольку UDP является протоколом без сохранения состояния, connect () просто выполняет системный вызов, который выясняет, как маршрутизировать пакеты на основе адреса и с каким интерфейсом (и, следовательно, IP-адресом), с которым он должен связываться. addr() возвращает массив, содержащий семейство (AF_INET), локальный порт и локальный адрес (что мы и хотим) сокета.
12 ответов
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"
Hostname
Простой способ получить имя хоста в Ruby:
require 'socket'
hostname = Socket.gethostname
Уловка в том, что это зависит от хоста, который знает свое имя, потому что он использует gethostname
или же uname
системный вызов, поэтому он не будет работать для исходной проблемы.
Функционально это идентично hostname
Ответ, без вызова внешней программы. Имя хоста может быть или не быть полностью определенным, в зависимости от конфигурации машины.
Айпи адрес
Начиная с ruby 1.9, вы также можете использовать библиотеку Socket для получения списка локальных адресов. ip_address_list
возвращает массив объектов AddrInfo. То, как вы выберете его, будет зависеть от того, что вы хотите сделать, и от того, сколько интерфейсов у вас есть, но вот пример, который просто выбирает первый IP-адрес без обратной связи в виде строки:
require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
Попробуй это:
host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host # Output the hostname
Сервер обычно имеет более одного интерфейса, по крайней мере, один частный и один общедоступный.
Поскольку все ответы здесь имеют дело с этим простым сценарием, более чистый способ - спросить у Socket текущий ip_address_list()
как в:
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
Оба возвращают объект Addrinfo, поэтому, если вам нужна строка, вы можете использовать ip_address()
метод, как в:
ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?
Вы можете легко найти более подходящее решение для вашего случая, изменив методы Addrinfo, используемые для фильтрации требуемого адреса интерфейса.
Самый простой host_with_port
в controller.rb
host_port= request.host_with_port
Этот IP-адрес, используемый здесь, принадлежит Google, но вы можете использовать любой доступный IP-адрес.
require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
Аналогично ответу с использованием hostname
, используя внешний uname
команда в UNIX/LINUX:
hostname = `uname -n`.chomp.sub(/\..*/,'') # stripping off "\n" and the network name if present
для используемых IP-адресов (ваша машина может иметь несколько сетевых интерфейсов), вы можете использовать что-то вроде этого:
# 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']
Принятый ответ работает, но вы должны создать сокет для каждого запроса, и он не работает, если сервер находится в локальной сети и / или не подключен к Интернету. Я полагаю, что приведенное ниже будет работать всегда, так как оно выполняет синтаксический анализ заголовка запроса.
request.env["SERVER_ADDR"]
Поместите выделенную часть в кавычки:
`dig #{request.host} +short`.strip # dig gives a newline at the end
Или просто request.host
если вам все равно, IP это или нет.
Скорее всего, у вас будет несколько IP-адресов на каждом компьютере (127.0.0.1, 192.168.0.1 и т. Д.). Если вы используете *NIX в качестве своей ОС, я бы предложил использовать hostname
, а затем запустить DNS посмотреть на это. Вы должны иметь возможность использовать /etc/hosts, чтобы определить локальное имя хоста для разрешения IP-адреса для этого компьютера. В Windows есть похожая функциональность, но я не использовал ее, так как Windows 95 была передовой.
Другим вариантом может быть поиск службы поиска, например WhatIsMyIp.com. Эти парни ответят вам вашим реальным IP-адресом. Это также то, что вы можете легко настроить с помощью сценария Perl на локальном сервере, если хотите. Я полагаю, что примерно три строки кода для вывода удаленного IP-адреса из%ENV должны вас охватить.
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}\ /)
Пара ответов с require 'socket'
хорошо выглядишь. Те, кто с request.blah_blah_blah, предполагают, что вы используете Rails.
IO должен быть доступен постоянно. Единственная проблема с этим сценарием заключается в том, что если ifconfig
выводится в другом поместье на ваших системах, тогда вы получите разные результаты для IP. Поиск имени хоста должен быть твердым как Sears.
Попробуйте: Request.remote_ip
remote_ip ()
Определить исходящий IP-адрес. REMOTE_ADDR - это стандарт, но он потерпит неудачу, если пользователь находится за прокси-сервером. HTTP_CLIENT_IP и / или HTTP_X_FORWARDED_FOR устанавливаются прокси, поэтому проверьте их, если REMOTE_ADDR является прокси. HTTP_X_FORWARDED_FOR может быть списком с разделителями-запятыми в случае нескольких цепочек прокси; последний недоверенный адрес - это исходящий IP.
Обновление: Ой, извините, я неправильно прочитал документацию.