2008-09-03 5 views
73

Tôi đang trong quá trình duy trì ứng dụng Ruby on Rails và đang tìm kiếm một cách dễ dàng để tìm tên máy chủ hoặc địa chỉ IP của hộp tôi đang truy cập (vì đó là VM và các phiên bản mới có thể có các tên máy chủ hoặc địa chỉ IP khác nhau). Có một cách nhanh chóng và dễ dàng để làm điều này trong Ruby on Rails?Nhận tên máy chủ hoặc IP trong Ruby on Rails

Edit: Câu trả lời dưới đây là chính xác nhưng rõ Craig cung cấp rất hữu ích (xem liên kết cũng được cung cấp trong câu trả lời):

Các [dưới đây] code KHÔNG tạo ra một kết nối hoặc gửi bất kỳ gói tin (để 64.233.187.99 là google). Vì UDP là giao thức không trạng thái kết nối() chỉ gọi hệ thống tìm cách định tuyến các gói dựa trên địa chỉ và giao diện (và do đó địa chỉ IP) . addr() trả về một mảng chứa họ (AF_INET), cổng cục bộ và địa chỉ cục bộ (trong đó là những gì chúng ta muốn) của ổ cắm.

Trả lời

45

Từ 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" 
+0

Cảm ơn bạn! Điều này làm việc hoàn hảo cho tôi :-) –

+1

@TopherFangio là IP này 64.233.187,99? –

+1

@ user422543 Mỗi chỉnh sửa trong câu hỏi ở trên, địa chỉ IP thuộc về Google. –

0

thử: Request.remote_ip

remote_ip()

Xác định nguồn gốc địa chỉ IP. REMOTE_ADDR là tiêu chuẩn nhưng sẽ không thành công nếu người dùng ở sau proxy. HTTP_CLIENT_IP và/hoặc HTTP_X_FORWARDED_FOR được đặt bởi proxy để kiểm tra nếu REMOTE_ADDR là proxy. HTTP_X_FORWARDED_FOR có thể là danh sách được phân tách bằng dấu phẩy trong trường hợp nhiều proxy bị xích; địa chỉ cuối cùng mà không đáng tin cậy là IP gốc.

Cập nhật: Rất tiếc, xin lỗi tôi đã đọc sai tài liệu.

+0

Điều này cung cấp cho bạn địa chỉ IP của người dùng gửi yêu cầu tới ứng dụng Rails chứ không phải địa chỉ IP của máy đang chạy ứng dụng Rails. – jsears

22

Hãy thử điều này:

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

Tôi thích Socket.gethostname cho độ tinh khiết, nhưng đối với một tra cứu đơn giản trên một hệ thống mà bạn biết 'hostname' sẽ hoạt động, bạn không thể đánh bại nó để đơn giản –

+0

bạn cũng có thể làm' uname -n'.sub (/\..*/, '') – Tilo

1

Bạn có thể sẽ thấy mình có nhiều địa chỉ IP trên mỗi máy (127.0.0.1, 192.168.0.1, vv). Nếu bạn đang sử dụng * NIX làm hệ điều hành của bạn, tôi khuyên bạn nên sử dụng hostname và sau đó chạy DNS tra cứu trên đó. Bạn sẽ có thể sử dụng/etc/hosts để xác định tên máy cục bộ để giải quyết địa chỉ IP cho máy đó. Có chức năng tương tự trên Windows, nhưng tôi đã không sử dụng nó kể từ Windows 95 là cạnh chảy máu.

Tùy chọn khác sẽ là truy cập dịch vụ tra cứu như WhatIsMyIp.com. Những kẻ này sẽ trả lại địa chỉ IP trong thế giới thực của bạn cho bạn. Đây cũng là một cái gì đó mà bạn có thể dễ dàng thiết lập với một kịch bản Perl trên một máy chủ địa phương nếu bạn thích. Tôi tin rằng 3 dòng hoặc nhiều mã để xuất IP từ xa từ% ENV sẽ bao gồm bạn.

+0

WhatIsMyIP.com sẽ không hoạt động nếu không có truy cập internet bên ngoài. –

124

Hostname

Một cách đơn giản để chỉ nhận được tên máy trong Ruby là:

Nắm bắt được điều này dựa trên máy chủ biết tên riêng của nó bởi vì nó sử dụng cuộc gọi hệ thống gethostname hoặc uname, vì vậy nó sẽ không hoạt động đối với vấn đề ban đầu.

Chức năng này giống hệt với câu trả lời hostname, mà không cần gọi chương trình bên ngoài. Tên máy chủ có thể hoặc không đủ điều kiện, tùy thuộc vào cấu hình của máy.


IP Address

Kể từ ruby ​​1.9, bạn cũng có thể sử dụng thư viện socket để có được một danh sách các địa chỉ địa phương. ip_address_list trả về một mảng gồm AddrInfo đối tượng. Làm thế nào bạn chọn từ nó sẽ phụ thuộc vào những gì bạn muốn làm và có bao nhiêu giao diện mà bạn có, nhưng đây là một ví dụ mà chỉ đơn giản chọn không loopback địa chỉ IPV4 IP đầu tiên như là một chuỗi:

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

Socket.gethostname không phải lúc nào cũng trả về FQDN. Sử dụng 'hostname'.strip có thể đáng tin cậy hơn nếu FQDN được mong muốn. –

+0

Ổ cắm. gethostname dường như không phải lúc nào cũng ổn định, xem bình luận http://stackoverflow.com/q/14112955/32453 – rogerdpack

2

Đặt phần tô đậm in backticks:

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

Hoặc chỉ request.host nếu bạn không quan tâm dù đó là IP hay không.

7

đơn giản nhất là host_with_port trong controller.rb

host_port= request.host_with_port 
+1

nhược điểm là bạn phải ở trong bộ điều khiển để truy cập yêu cầu .. nhưng ý tưởng hay! – Tilo

+0

Có vẻ như các câu trả lời khác chỉ là hack, trong khi điều này làm đúng cách. Tại sao nó được chôn dưới chúng? – tbodt

2

Các công trình trả lời chấp nhận nhưng bạn phải tạo ra một ổ cắm cho mọi yêu cầu và nó không hoạt động nếu máy chủ là trên một mạng cục bộ và/hoặc không kết nối lên internet. Dưới đây, tôi tin rằng sẽ luôn luôn hoạt động vì nó đang phân tích cú pháp tiêu đề yêu cầu.

request.env["SERVER_ADDR"] 
+3

OP không thực sự nói rằng họ có quyền truy cập vào đối tượng yêu cầu tại thời điểm mà anh ta cần địa chỉ IP. Các giải pháp dựa trên Socket chung chung hơn –

9

Địa chỉ IP này được sử dụng ở đây là Google, nhưng bạn có thể sử dụng bất kỳ IP có thể truy cập nào.

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

Máy chủ thường có nhiều giao diện, ít nhất một giao diện riêng tư và một công khai.

Vì tất cả các câu trả lời ở đây đối phó với kịch bản đơn giản này, một cách sạch là yêu cầu Socket cho dòng điện ip_address_list() như trong:

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 

Cả hai trả về một đối tượng Addrinfo, vì vậy nếu bạn cần một chuỗi bạn có thể sử dụng phương pháp ip_address(), như trong:

ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil? 

bạn có thể dễ dàng làm việc ra các giải pháp phù hợp hơn để trường hợp của bạn thay đổi phương pháp Addrinfo sử dụng để lọc địa chỉ giao diện yêu cầu.

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}\ /) 

Hai câu trả lời với require 'socket' có vẻ tốt. Những người có yêu cầu.blah_blah_blah giả sử rằng bạn đang sử dụng Rails.

IO luôn sẵn sàng. Vấn đề duy nhất với kịch bản này sẽ là nếu ifconfig là đầu ra trong một trang viên khác trên các hệ thống của bạn, thì bạn sẽ nhận được các kết quả khác nhau cho IP. Tên máy chủ tìm kiếm nên chắc chắn như Sears.

2

Tương tự như các câu trả lời bằng hostname, sử dụng bên ngoài uname lệnh trên UNIX/LINUX:

hostname = `uname -n`.chomp.sub(/\..*/,'') # stripping off "\n" and the network name if present 

cho các địa chỉ IP được sử dụng (máy tính của bạn có thể có nhiều giao diện mạng), bạn có thể sử dụng một cái gì đó như này:

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