Ruby onRailsでホスト名またはIPを取得する


80

私はRubyon Railsアプリを保守している最中であり、使用しているボックスのホスト名またはIPアドレスを見つける簡単な方法を探しています(VMであり、新しいインスタンスのホスト名またはIPアドレスが異なる可能性があるため) 。Ruby on Railsでこれを行うための迅速で簡単な方法はありますか?

編集:以下の答えは正しいですが、クレイグが提供した説明は役に立ちます(答えの提供されたリンクも参照してください):

[以下の]コードは、接続を確立したり、パケットを送信したりしません(Googleである64.233.187.99に)。UDPはステートレスプロトコルであるため、connect()は、アドレスと、バインドする必要のあるインターフェイス(したがってIPアドレス)に基づいてパケットをルーティングする方法を判断するシステムコールを行うだけです。addr()は、ソケットのファミリ(AF_INET)、ローカルポート、およびローカルアドレス(必要なもの)を含む配列を返します。

回答:


50

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"

1
@ user422543上記の質問の編集によると、IPアドレスはGoogleに属しています。
Topher Fangio 2013

138

ホスト名

Rubyでホスト名を取得する簡単な方法は次のとおりです。

require 'socket'
hostname = Socket.gethostname

キャッチは、ホストがgethostnameまたはunameシステムコールのいずれかを使用するため、ホストが自身の名前を知っていることに依存しているため、元の問題では機能しないことです。

機能的にはhostname、外部プログラムを呼び出さなくても、これは答えと同じです。ホスト名は、マシンの構成に応じて、完全修飾される場合とされない場合があります。


IPアドレス

ruby 1.9以降、Socketライブラリを使用してローカルアドレスのリストを取得することもできます。 AddrInfoオブジェクトのip_address_list配列を返します。どちらを選択するかは、実行する内容と使用するインターフェイスの数によって異なりますが、最初の非ループバックIPV4IPアドレスを文字列として選択する例を次に示します。

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

Socket.gethostnameは常にFQDNを返すとは限りません。FQDNが必要な場合は、「hostname」.stripを使用する方が信頼性が高い場合があります。
Travis Bear

ソケット。gethostnameが常に明らかに安定していない、コメントを見るstackoverflow.com/q/14112955/32453
rogerdpack

公式ドキュメントのページ:ruby-doc.org/stdlib/libdoc/socket/rdoc/...
HarlemSquirrel

24

これを試して:

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

4
私はSocket.gethostnameの純度が好きですが、機能することがわかっているシステムでの単純なルックアップでは、単純hostnameにするためにそれを打ち負かすことはできません
Dave Smylie 2011

uname -n.sub(/ \ .. * /、 '')
Tilo

13

サーバーには通常、少なくとも1つのプライベートと1つのパブリックの複数のインターフェイスがあります。

ここでのすべての答えはこの単純なシナリオを扱っているので、よりクリーンな方法は、次のように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メソッドを変更することで、ケースに適したソリューションを簡単に見つけることができます。


9

ここで使用されているこのIPアドレスはGoogleのものですが、アクセス可能な任意のIPを使用できます。

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

8

最も単純なのはhost_with_portcontroller.rbです

host_port= request.host_with_port

2
欠点は、リクエストにアクセスするにはコントローラーにいる必要があることです。しかし、良い考えです。
ティロ2012

他の答えは単なるハックのようですが、これは正しい方法です。なぜそれは彼らの下に埋もれているのですか?
tbodt 2014年

2

受け入れられた回答は機能しますが、すべての要求に対してソケットを作成する必要があり、サーバーがローカルネットワーク上にあるか、インターネットに接続されていない場合は機能しません。以下では、リクエストヘッダーを解析しているため、常に機能すると思います。

request.env["SERVER_ADDR"]

3
OPは、IPアドレスが必要な時点でリクエストオブジェクトにアクセスできるとは実際には言っていませんでした。ソケットベースのソリューションはより一般的です
Chris McCauley 2012

2

ハイライトされた部分をバッククォートに入れます。

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

またはrequest.host、それがIPであるかどうかを気にしない場合。


2

UNIX / LINUXでhostname外部unameコマンドを使用して、を使用した回答と同様です。

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

1

各マシンに複数のIPアドレス(127.0.0.1、192.168.0.1など)があることに気付くでしょう。OSとして* NIXを使用している場合は、を使用しhostnameて、DNSルックアップを実行することをお勧めします。/ etc / hostsを使用して、そのマシンのIPアドレスに解決するローカルホスト名を定義できるはずです。Windowsにも同様の機能がありますが、Windows 95が最先端だったので、使っていません。

他のオプションは、WhatIsMyIp.comのようなルックアップサービスをヒットすることです。これらの人はあなたの実際のIPアドレスをあなたにキックバックします。これは、必要に応じて、ローカルサーバー上のPerlスクリプトを使用して簡単にセットアップできるものでもあります。%ENVからリモートIPを出力するための3行程度のコードで対応できると思います。


外部インターネットアクセスがない場合、WhatIsMyIP.comは機能しません。
ブリキの

1
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のようにしっかりしている必要があります。


0

試してください:Request.remote_ip

remote_ip()

発信元IPアドレスを決定します。REMOTE_ADDRが標準ですが、ユーザーがプロキシの背後にいる場合は失敗します。HTTP_CLIENT_IPおよび/またはHTTP_X_FORWARDED_FORはプロキシによって設定されるため、REMOTE_ADDRがプロキシであるかどうかを確認してください。HTTP_X_FORWARDED_FORは、複数のチェーンプロキシの場合、コンマ区切りのリストにすることができます。信頼されていない最後のアドレスは発信元IPです。

更新:おっと、申し訳ありませんが、ドキュメントを読み間違えました。


これにより、Railsアプリを実行しているマシンのIPアドレスではなく、Railsアプリにリクエストを発行しているユーザーのIPアドレスがわかります。
jsears 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.