Laquelle des méthodes suivantes est la meilleure et la plus portable pour obtenir le nom d'hôte de l'ordinateur actuel en Java?
Runtime.getRuntime().exec("hostname")
contre
InetAddress.getLocalHost().getHostName()
Laquelle des méthodes suivantes est la meilleure et la plus portable pour obtenir le nom d'hôte de l'ordinateur actuel en Java?
Runtime.getRuntime().exec("hostname")
contre
InetAddress.getLocalHost().getHostName()
Réponses:
À strictement parler - vous n'avez pas d'autre choix que d'appeler l'un
hostname(1)
ou l' autre - sur Unixgethostname(2)
. Il s'agit du nom de votre ordinateur. Toute tentative de déterminer le nom d'hôte par une adresse IP comme celle-ciest voué à l'échec dans certaines circonstances:
Ne confondez pas non plus le nom d'une adresse IP avec le nom de l'hôte (nom d'hôte). Une métaphore pourrait être plus claire:
Cela illustre à peu près je pense.
La bonne nouvelle est: le vrai nom d'hôte n'est généralement pas nécessaire. Dans la plupart des cas, tout nom qui se résout en une adresse IP sur cet hôte fera l'affaire. (L'étranger pourrait entrer dans la ville par Northgate, mais les habitants utiles traduisent la partie "2ème à gauche".)
Si les cas de coin restantes vous devez utiliser la définitive source de ce paramètre de configuration - qui est la fonction C
gethostname(2)
. Cette fonction est également appelée par le programmehostname
.la source
InetAddress.getLocalHost().getHostName()
est le moyen le plus portable.exec("hostname")
appelle en fait le système d'exploitation pour exécuter lahostname
commande.Voici quelques autres réponses connexes sur SO:
EDIT: Vous devriez jeter un œil à la réponse d'AH ou à la réponse d' Arnout Engelen pour savoir pourquoi cela pourrait ne pas fonctionner comme prévu, selon votre situation. En tant que réponse pour cette personne qui a spécifiquement demandé le portable, je pense toujours que
getHostName()
c'est bien, mais ils soulèvent de bons points qui devraient être pris en considération.la source
InetAddress.getLocalHost()
dans certains cas, renvoie le périphérique de bouclage. Dans ce cas,getHostName()
renvoie "localhost", ce qui n'est pas très utile.Comme d'autres l'ont noté, l'obtention du nom d'hôte basé sur la résolution DNS n'est pas fiable.
Étant donné que cette question est malheureusement toujours d'actualité en 2018 , je voudrais partager avec vous ma solution indépendante du réseau, avec quelques tests sur différents systèmes.
Le code suivant tente d'effectuer les opérations suivantes:
Sous Windows
Lisez la
COMPUTERNAME
variable d'environnementSystem.getenv()
.Exécutez
hostname.exe
et lisez la réponseSous Linux
Lisez la
HOSTNAME
variable d'environnementSystem.getenv()
Exécutez
hostname
et lisez la réponseLire
/etc/hostname
(pour ce faire, je suis encat
train d' exécuter, car l'extrait contient déjà du code à exécuter et à lire. Une simple lecture du fichier serait cependant préférable).Le code:
Résultats pour différents systèmes d'exploitation:
macOS 10.13.2
OpenSuse 13.1
Ubuntu 14.04 LTS Celui-ci est un peu étrange car
echo $HOSTNAME
retourne le nom d'hôte correct, maisSystem.getenv("HOSTNAME")
ne fait pas:EDIT: Selon legolas108 ,
System.getenv("HOSTNAME")
fonctionne sur Ubuntu 14.04 si vous exécutezexport HOSTNAME
avant d'exécuter le code Java.Windows 7
Windows 10
Les noms des machines ont été remplacés mais j'ai conservé la capitalisation et la structure. Notez la nouvelle ligne supplémentaire lors de l'exécution
hostname
, vous devrez peut-être en tenir compte dans certains cas.la source
export HOSTNAME
avant d'exécuter le code Java sur Ubuntu 14.04 LTS, il est également renvoyé parSystem.getenv("HOSTNAME")
.export HOSTNAME
que Java l'utilise? Je pensais que ce devrait être un var env par défaut comme PATH.\A
délimiteur n'est qu'un hack pour lire l'intégralité du InputStream à l'aide de aScanner
.InetAddress.getLocalHost().getHostName()
est mieux (comme expliqué par Nick), mais toujours pas très bonUn hôte peut être connu sous de nombreux noms d'hôtes différents. Habituellement, vous rechercherez le nom d'hôte de votre hôte dans un contexte spécifique.
Par exemple, dans une application Web, vous recherchez peut-être le nom d'hôte utilisé par la personne qui a émis la demande que vous gérez actuellement. La meilleure façon de trouver celle-ci dépend du cadre que vous utilisez pour votre application Web.
Dans une sorte d'autre service accessible sur Internet, vous voudrez que le nom d'hôte via lequel votre service est disponible de «l'extérieur». En raison de procurations, de pare-feu, etc., il se peut que ce ne soit même pas un nom d'hôte sur la machine sur laquelle votre service est installé - vous pouvez essayer de trouver une valeur par défaut raisonnable, mais vous devriez certainement le rendre configurable pour celui qui l'installe.
la source
Bien que ce sujet ait déjà été répondu, il y a plus à dire.
Tout d'abord: il est clair que nous avons besoin de quelques définitions ici. Le
InetAddress.getLocalHost().getHostName()
vous donne le nom de l'hôte vu du point de vue du réseau . Les problèmes avec cette approche sont bien documentés dans les autres réponses: elle nécessite souvent une recherche DNS, elle est ambiguë si l'hôte a plusieurs interfaces réseau et elle échoue tout simplement parfois (voir ci-dessous).Mais sur n'importe quel système d'exploitation, il existe également un autre nom. Nom de l'hôte qui est défini très tôt dans le processus de démarrage, bien avant l'initialisation du réseau. Windows y fait référence sous le nom de calcul , Linux l'appelle nom d'hôte du noyau et Solaris utilise le mot nodename . Je préfère le mot nom_ordinateur , je vais donc utiliser ce mot à partir de maintenant.
Recherche du nom d'ordinateur
Sous Linux / Unix, le nom d'ordinateur est ce que vous obtenez de la fonction C
gethostname()
, ou de lahostname
commande du shell ou deHOSTNAME
la variable d'environnement dans des shells de type Bash.Sous Windows, le nom d'ordinateur est ce que vous obtenez de la variable d'environnement
COMPUTERNAME
ou de laGetComputerName
fonction Win32 .Java n'a aucun moyen d'obtenir ce que j'ai défini comme «nom d'ordinateur». Bien sûr, il existe des solutions de contournement comme décrit dans d'autres réponses, comme pour les appels Windows
System.getenv("COMPUTERNAME")
, mais sur Unix / Linux, il n'y a pas de bonne solution de contournement sans recourir à JNI / JNA ouRuntime.exec()
. Si cela ne vous dérange pas une solution JNI / JNA, il y a gethostname4j qui est très simple et très facile à utiliser.Passons à deux exemples, l'un de Linux et l'autre de Solaris, qui montrent comment vous pouvez facilement vous retrouver dans une situation où vous ne pouvez pas obtenir le nom d'ordinateur à l'aide de méthodes Java standard.
Exemple Linux
Sur un système nouvellement créé, où l'hôte lors de l'installation a été nommé «chicago», nous changeons maintenant le nom d'hôte du noyau:
Maintenant, le nom d'hôte du noyau est 'dallas', comme en témoigne la commande hostname:
Mais nous avons encore
Il n'y a aucune mauvaise configuration là-dedans. Cela signifie simplement que le nom en réseau de l'hôte (ou plutôt le nom de l'interface de bouclage) est différent du nom d'ordinateur de l'hôte.
Maintenant, essayez de l'exécuter
InetAddress.getLocalHost().getHostName()
et cela lancera java.net.UnknownHostException. Vous êtes fondamentalement coincé. Il n'y a aucun moyen de récupérer ni la valeur «dallas» ni la valeur «chicago».Exemple Solaris
L'exemple ci-dessous est basé sur Solaris 11.3.
L'hôte a été délibérément configuré pour que le nom de bouclage <> nodename.
En d'autres termes, nous avons:
et le contenu de / etc / hosts:
et le résultat de la commande hostname serait:
Tout comme dans l'exemple Linux, un appel à
InetAddress.getLocalHost().getHostName()
échouera avecTout comme l'exemple Linux, vous êtes maintenant bloqué. Il n'y a aucun moyen de récupérer ni la valeur «dallas» ni la valeur «chicago».
Quand allez-vous vraiment vous battre avec ça?
Très souvent, vous constaterez que
InetAddress.getLocalHost().getHostName()
cela retournera en effet une valeur qui est égale au nom de l'ordinateur. Il n'y a donc aucun problème (à l'exception de la surcharge supplémentaire de la résolution de noms).Le problème survient généralement dans les environnements PaaS où il y a une différence entre le nom de l'ordinateur et le nom de l'interface de bouclage. Par exemple, des personnes signalent des problèmes dans Amazon EC2.
Rapports de bogues / RFE
Un peu de recherche révèle ce rapport de RFE: link1 , lien2 . Cependant, à en juger par les commentaires sur ce rapport, le problème semble avoir été largement mal compris par l'équipe du JDK, il est donc peu probable qu'il soit traité.
J'aime la comparaison dans le RFE avec d'autres langages de programmation.
la source
Les variables d'environnement peuvent également fournir un moyen utile -
COMPUTERNAME
sous Windows,HOSTNAME
sur la plupart des shells Unix / Linux modernes.Voir: https://stackoverflow.com/a/17956000/768795
J'utilise ces méthodes comme des méthodes «supplémentaires»
InetAddress.getLocalHost().getHostName()
, car comme plusieurs personnes le soulignent, cette fonction ne fonctionne pas dans tous les environnements.Runtime.getRuntime().exec("hostname")
est un autre supplément possible. À ce stade, je ne l'ai pas utilisé.la source
StringUtils
, son fourni par le projet Apache commons-lang. L'utiliser, ou quelque chose comme ça, est fortement recommandé.System.getenv("HOSTNAME")
est sorti nul sur Mac via Beanshell pour Java, mais aPATH
été extrait correctement. Je pourrais aussi le faireecho $HOSTNAME
sur Mac, juste System.getenv ("HOSTNAME") semble avoir un problème. Étrange.La façon la plus portable d'obtenir le nom d'hôte de l'ordinateur actuel en Java est la suivante:
la source
Si vous n'êtes pas contre l'utilisation d'une dépendance externe de maven central, j'ai écrit gethostname4j pour résoudre ce problème par moi-même. Il utilise simplement JNA pour appeler la fonction gethostname de libc (ou obtient le ComputerName sous Windows) et vous le renvoie sous forme de chaîne.
https://github.com/mattsheppard/gethostname4j
la source
la source
Juste une ligne ... multiplateforme (Windows-Linux-Unix-Mac (Unix)) [Fonctionne toujours, aucun DNS requis]:
Vous avez terminé !!
la source
InetAddress.getLocalHost (). GetHostName () est le meilleur moyen de sortir des deux car c'est la meilleure abstraction au niveau du développeur.
la source