Obtenir le nom d’hôte ou l’adresse IP dans Ruby on Rails

Je suis en train de maintenir une application Ruby on Rails et je cherche un moyen facile de trouver le nom d’hôte ou l’adresse IP de la boîte sur laquelle je suis (car il s’agit d’une VM et les nouvelles instances peuvent avoir des noms d’hôte ou des adresses IP différents) . Existe-t-il un moyen simple et rapide de le faire dans Ruby on Rails?

Edit: La réponse ci-dessous est correcte mais la clarification fournie par Craig est utile (voir aussi le lien fourni dans la réponse):

Le code [ci-dessous] ne fait pas de connexion ou n’envoie aucun paquet (à 64.233.187.99 qui est google). Comme UDP est un protocole sans état, connect () effectue simplement un appel système qui détermine comment acheminer les paquets en fonction de l’adresse et de l’interface (et donc de l’adresse IP) auxquelles il doit être associé. addr () renvoie un tableau contenant la famille (AF_INET), le port local et l’adresse locale (ce que nous voulons) du socket.

    De 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" 

    Nom d’hôte

    Une manière simple d’obtenir le nom d’hôte dans Ruby est la suivante:

     require 'socket' hostname = Socket.gethostname 

    Le problème est que cela dépend de l’hôte qui connaît son propre nom, car il utilise l’appel système gethostname ou uname , de sorte qu’il ne fonctionnera pas pour le problème d’origine.

    Fonctionnellement, ceci est identique à la réponse du hostname , sans appeler un programme externe. Le nom d’hôte peut être ou ne pas être entièrement qualifié, selon la configuration de la machine.


    Adresse IP

    Depuis Ruby 1.9, vous pouvez également utiliser la bibliothèque Socket pour obtenir une liste d’adresses locales. ip_address_list renvoie un tableau d’objects AddrInfo . La manière dont vous choisirez dépendra de ce que vous voulez faire et du nombre d’interfaces que vous avez, mais voici un exemple qui sélectionne simplement la première adresse IP IPV4 sans bouclage sous forme de chaîne:

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

    Essaye ça:

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

    Un serveur a généralement plusieurs interfaces, au moins une privée et une publique.

    Comme toutes les réponses concernent ce scénario simple, une méthode plus propre consiste à demander à Socket la liste actuelle ip_address_list() comme dans:

     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 

    Les deux renvoient un object Addrinfo, donc si vous avez besoin d’une chaîne, vous pouvez utiliser la méthode ip_address() , comme dans:

     ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil? 

    Vous pouvez facilement trouver la solution la plus adaptée à votre cas en modifiant les méthodes Addrinfo utilisées pour filtrer l’adresse d’interface requirejse.

    Cette adresse IP utilisée ici est celle de Google, mais vous pouvez utiliser n’importe quelle adresse IP accessible.

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

    Le plus simple est host_with_port dans controller.rb

     host_port= request.host_with_port 

    La réponse acceptée fonctionne mais vous devez créer un socket pour chaque requête et cela ne fonctionne pas si le serveur se trouve sur un réseau local et / ou n’est pas connecté à Internet. Le tableau ci-dessous, je crois, fonctionnera toujours car il parsing l’en-tête de la requête.

     request.env["SERVER_ADDR"] 

    Mettez la partie en surbrillance dans les backticks:

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

    Ou simplement request.host si vous ne vous souciez pas de savoir si c’est une adresse IP ou non.

    Similaire à la réponse en utilisant hostname , en utilisant la commande uname externe sous UNIX / LINUX:

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

    pour les adresses IP utilisées (votre machine peut avoir plusieurs interfaces réseau), vous pouvez utiliser quelque chose comme ceci:

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

    Vous vous retrouverez probablement avec plusieurs adresses IP sur chaque machine (127.0.0.1, 192.168.0.1, etc.). Si vous utilisez * NIX comme système d’exploitation, je vous suggère d’utiliser hostname , puis d’exécuter un DNS sur celui-ci. Vous devriez pouvoir utiliser / etc / hosts pour définir le nom d’hôte local à résoudre en adresse IP pour cette machine. Il existe des fonctionnalités similaires sous Windows, mais je ne l’ai pas utilisé depuis que Windows 95 était à la pointe de la technologie.

    L’autre option serait de bash un service de recherche comme WhatIsMyIp.com . Ces gars vont vous redonner votre adresse IP du monde réel. C’est aussi quelque chose que vous pouvez facilement configurer avec un script Perl sur un serveur local si vous préférez. Je crois que 3 lignes ou plus de code pour sortir l’IP distant de% ENV devraient vous couvrir.

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

    Le couple de réponses avec require 'socket' semble bien. Ceux avec request.blah_blah_blah supposent que vous utilisez Rails.

    IO devrait être disponible tout le temps. Le seul problème avec ce script serait que si ifconfig est ifconfig dans un autre manoir sur vos systèmes, vous obtiendrez des résultats différents pour l’IP. La recherche de nom d’hôte devrait être solide comme Sears.

    essayez: Request.remote_ip

    remote_ip ()

    Déterminez l’adresse IP d’origine. REMOTE_ADDR est la norme mais échouera si l’utilisateur se trouve derrière un proxy. HTTP_CLIENT_IP et / ou HTTP_X_FORWARDED_FOR sont définis par des proxy, donc vérifiez-les si REMOTE_ADDR est un proxy. HTTP_X_FORWARDED_FOR peut être une liste séparée par des virgules dans le cas de plusieurs proxys chaînés; la dernière adresse non approuvée est l’adresse IP d’origine.

    Mise à jour: Oups, désolé j’ai mal interprété la documentation.