Получение имени хоста или IP в Ruby on Rails - PullRequest
76 голосов
/ 04 сентября 2008

Я нахожусь в процессе обслуживания приложения Ruby on Rails и ищу простой способ найти имя хоста или IP-адрес ящика, на котором я работаю (так как это виртуальная машина, и новые экземпляры могут иметь разные имена хостов или IP-адреса). Есть ли быстрый и простой способ сделать это в Ruby on Rails?

Редактировать: приведенный ниже ответ является правильным, но предоставленное Крейгом разъяснение полезно (см. Также предоставленную ссылку в ответе):

Код [ниже] НЕ делает подключить или отправить любые пакеты (для 64.233.187.99, который является Google). Поскольку UDP является протоколом без сохранения состояния, connect () просто делает системный вызов, который выясняет, как маршрутизировать пакеты на основании адреса и что интерфейс (и, следовательно, IP-адрес) это должно привязать к. addr () возвращает массив, содержащий семейство (AF_INET), локальный порт и локальный адрес (который это то, что мы хотим) сокета.

Ответы [ 12 ]

132 голосов
/ 08 октября 2009

Hostname

Простой способ получить имя хоста в Ruby:

require 'socket'
hostname = Socket.gethostname

Проблема в том, что хост полагается на свое имя, поскольку использует системный вызов gethostname или uname, поэтому он не будет работать для исходной проблемы.

Функционально это идентично ответу hostname, без вызова внешней программы. Имя хоста может быть или не быть полным, в зависимости от конфигурации машины.


IP-адрес

Начиная с 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
46 голосов
/ 04 сентября 2008

С 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"
23 голосов
/ 04 сентября 2008

Попробуйте это:

host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host               # Output the hostname
11 голосов
/ 18 октября 2011

Сервер обычно имеет более одного интерфейса, по крайней мере, один частный и один общедоступный.

Поскольку все ответы здесь касаются этого простого сценария, более понятным способом является запрос сокета для текущей 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, используемые для фильтрации требуемого адреса интерфейса.

9 голосов
/ 17 февраля 2011

Этот IP-адрес используется здесь от Google, но вы можете использовать любой доступный IP-адрес.

require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
7 голосов
/ 14 июля 2010

Простейшее значение host_with_port в controller.rb

host_port= request.host_with_port
2 голосов
/ 28 сентября 2012

Аналогично ответу с использованием 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']
2 голосов
/ 18 января 2011

Принятый ответ работает, но вы должны создавать сокет для каждого запроса, и он не работает, если сервер находится в локальной сети и / или не подключен к Интернету. Я полагаю, что приведенное ниже будет работать всегда, поскольку оно выполняет синтаксический анализ заголовка запроса.

request.env["SERVER_ADDR"]
2 голосов
/ 25 октября 2009

Поместите выделенную часть в кавычки:

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

Или просто request.host, если вам все равно, IP это или нет.

1 голос
/ 18 ноября 2011
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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...