¿Cuál de las siguientes es la mejor y más portátil forma de obtener el nombre de host de la computadora actual en Java?
Runtime.getRuntime().exec("hostname")
vs
InetAddress.getLocalHost().getHostName()
¿Cuál de las siguientes es la mejor y más portátil forma de obtener el nombre de host de la computadora actual en Java?
Runtime.getRuntime().exec("hostname")
vs
InetAddress.getLocalHost().getHostName()
Respuestas:
Hablando estrictamente, no tiene más remedio que llamar a cualquiera de los dos
hostname(1)
, en Unixgethostname(2)
. Este es el nombre de tu computadora. Cualquier intento de determinar el nombre de host por una dirección IP como estaestá obligado a fallar en algunas circunstancias:
Tampoco confunda el nombre de una dirección IP con el nombre del host (nombre del host). Una metáfora podría aclararlo:
Esto lo ilustra más o menos, creo.
La buena noticia es: el nombre de host real generalmente no es necesario. En la mayoría de los casos, cualquier nombre que se resuelva en una dirección IP en este host funcionará. (El extraño podría ingresar a la ciudad por Northgate, pero los lugareños útiles traducen la parte de "segunda izquierda").
Si los casos de esquina restantes debe utilizar la definitiva fuente de esta opción de configuración - que es la función C
gethostname(2)
. Esa función también es llamada por el programahostname
.fuente
InetAddress.getLocalHost().getHostName()
Es la forma más portátil.exec("hostname")
en realidad llama al sistema operativo para ejecutar elhostname
comando.Aquí hay otras respuestas relacionadas sobre SO:
EDITAR: debe echar un vistazo a la respuesta de AH o la respuesta de Arnout Engelen para obtener detalles sobre por qué esto podría no funcionar como se esperaba, dependiendo de su situación. Como respuesta para esta persona que solicitó específicamente un dispositivo portátil, sigo pensando que
getHostName()
está bien, pero mencionan algunos puntos buenos que deberían considerarse.fuente
InetAddress.getLocalHost()
en algunos casos devuelve el dispositivo de bucle invertido. En ese caso,getHostName()
devuelve "localhost", que no es muy útil.Como otros han señalado, obtener el nombre de host basado en la resolución DNS no es confiable.
Como desafortunadamente esta pregunta aún es relevante en 2018 , me gustaría compartir con ustedes mi solución independiente de la red, con algunas ejecuciones de prueba en diferentes sistemas.
El siguiente código intenta hacer lo siguiente:
En Windows
Lea la
COMPUTERNAME
variable de entorno a travésSystem.getenv()
.Ejecuta
hostname.exe
y lee la respuestaEn Linux
Lea la
HOSTNAME
variable de entorno a través deSystem.getenv()
Ejecuta
hostname
y lee la respuestaLeer
/etc/hostname
(para hacer esto, lo estoy ejecutandocat
ya que el fragmento ya contiene código para ejecutar y leer. Simplemente leer el archivo sería mejor).El código:
Resultados para diferentes sistemas operativos:
macOS 10.13.2
OpenSuse 13.1
Ubuntu 14.04 LTS Este es un poco extraño ya que
echo $HOSTNAME
devuelve el nombre de host correcto, peroSystem.getenv("HOSTNAME")
no:EDITAR: Según legolas108 ,
System.getenv("HOSTNAME")
funciona en Ubuntu 14.04 si lo ejecutaexport HOSTNAME
antes de ejecutar el código Java.Windows 7
Windows 10
Los nombres de las máquinas han sido reemplazados pero mantuve las mayúsculas y la estructura. Tenga en cuenta la nueva línea adicional al ejecutar
hostname
, puede que tenga que tenerla en cuenta en algunos casos.fuente
export HOSTNAME
antes de ejecutar el código Java en Ubuntu 14.04 LTS también lo devuelveSystem.getenv("HOSTNAME")
.export HOSTNAME
que Java lo use? Pensé que debería ser un entorno predeterminado como PATH.\A
delimitador es solo un truco para leer todo el InputStream usando aScanner
.InetAddress.getLocalHost().getHostName()
es mejor (como explica Nick), pero aún no es muy buenoUn host se puede conocer con muchos nombres de host diferentes. Por lo general, buscará el nombre de host que tiene en un contexto específico.
Por ejemplo, en una aplicación web, es posible que esté buscando el nombre de host utilizado por quien emitió la solicitud que está manejando actualmente. La mejor manera de encontrarla depende del marco que esté utilizando para su aplicación web.
En algún otro tipo de servicio con conexión a Internet, querrá el nombre de host para el que está disponible su servicio desde el 'exterior'. Debido a los servidores proxy, los cortafuegos, etc., es posible que este ni siquiera sea un nombre de host en la máquina en la que está instalado su servicio; puede intentar obtener un valor predeterminado razonable, pero definitivamente debe hacer que esto sea configurable para quien lo instale.
fuente
Aunque este tema ya ha sido respondido, hay más que decir.
Primero que nada: Claramente necesitamos algunas definiciones aquí. El
InetAddress.getLocalHost().getHostName()
le da el nombre del host como se ve desde una perspectiva de red . Los problemas con este enfoque están bien documentados en las otras respuestas: a menudo requiere una búsqueda de DNS, es ambiguo si el host tiene múltiples interfaces de red y simplemente falla a veces (ver más abajo).Pero en cualquier sistema operativo también hay otro nombre. Un nombre del host que se define muy temprano en el proceso de arranque, mucho antes de que se inicialice la red. Windows se refiere a esto como nombre de computadora , Linux lo llama nombre de host del núcleo y Solaris usa la palabra nombrenodo . Me gusta más la palabra computername , así que usaré esa palabra de ahora en adelante.
Encontrar el nombre de la computadora
En Linux / Unix, el nombre de la computadora es lo que obtienes de la función C
gethostname()
, o elhostname
comando de la shell oHOSTNAME
la variable de entorno en shells tipo Bash.En Windows, el nombre del equipo es lo que obtienes de la variable de entorno
COMPUTERNAME
o laGetComputerName
función Win32 .Java no tiene forma de obtener lo que he definido como 'nombre de computadora'. Claro, hay soluciones como se describe en otras respuestas, como para las llamadas de Windows
System.getenv("COMPUTERNAME")
, pero en Unix / Linux no hay una buena solución sin recurrir a JNI / JNA oRuntime.exec()
. Si no le importa una solución JNI / JNA, hay gethostname4j, que es muy simple y muy fácil de usar.Pasemos con dos ejemplos, uno de Linux y otro de Solaris, que demuestran cómo puede entrar fácilmente en una situación en la que no puede obtener el nombre de la computadora utilizando métodos estándar de Java.
Ejemplo de Linux
En un sistema recién creado, donde el host durante la instalación ha sido nombrado como 'Chicago', ahora cambiamos el llamado nombre de host del núcleo:
Ahora el nombre de host del núcleo es 'dallas', como se desprende del comando hostname:
Pero todavia tenemos
No hay una mala configuración en esto. Simplemente significa que el nombre en red del host (o más bien el nombre de la interfaz de bucle invertido) es diferente del nombre de la computadora del host.
Ahora, intente ejecutar
InetAddress.getLocalHost().getHostName()
y arrojará java.net.UnknownHostException. Básicamente estás atrapado. No hay forma de recuperar ni el valor 'dallas' ni el valor 'chicago'.Ejemplo de Solaris
El siguiente ejemplo se basa en Solaris 11.3.
El host se configuró deliberadamente para que el nombre de bucle invertido <> nombrenodo.
En otras palabras tenemos:
y el contenido de / etc / hosts:
y el resultado del comando hostname sería:
Al igual que en el ejemplo de Linux, una llamada a
InetAddress.getLocalHost().getHostName()
fallará conAl igual que el ejemplo de Linux, ahora estás atascado. No hay forma de recuperar ni el valor 'dallas' ni el valor 'chicago'.
¿Cuándo realmente lucharás con esto?
Muy a menudo encontrará que
InetAddress.getLocalHost().getHostName()
, de hecho, devolverá un valor que es igual al nombre del equipo. Por lo tanto, no hay problema (a excepción de la sobrecarga adicional de la resolución de nombres).El problema surge típicamente en entornos PaaS donde hay una diferencia entre el nombre de la computadora y el nombre de la interfaz de bucle invertido. Por ejemplo, las personas informan problemas en Amazon EC2.
Informes de errores / RFE
Un poco de búsqueda revela este informe RFE: link1 , link2 . Sin embargo, a juzgar por los comentarios sobre ese informe, el tema parece haber sido mal entendido por el equipo de JDK, por lo que es poco probable que se aborde.
Me gusta la comparación en el RFE con otros lenguajes de programación.
fuente
Las variables de entorno también pueden proporcionar un medio útil,
COMPUTERNAME
en Windows,HOSTNAME
en la mayoría de los shells modernos de Unix / Linux.Ver: https://stackoverflow.com/a/17956000/768795
Los estoy utilizando como métodos "complementarios" para
InetAddress.getLocalHost().getHostName()
, como señalan varias personas, esa función no funciona en todos los entornos.Runtime.getRuntime().exec("hostname")
Es otro posible suplemento. En este momento, no lo he usado.fuente
StringUtils
, es proporcionado por el proyecto Apache commons-lang. Usarlo, o algo así, es muy recomendable.System.getenv("HOSTNAME")
salió nulo en Mac a través de Beanshell para Java, peroPATH
se extrajo bien. También podría hacerloecho $HOSTNAME
en Mac, solo System.getenv ("HOSTNAME") parece tener problemas. Extraño.La forma más portátil de obtener el nombre de host de la computadora actual en Java es la siguiente:
fuente
Si no está en contra de usar una dependencia externa de maven central, escribí gethostname4j para resolver este problema por mí mismo. Simplemente usa JNA para llamar a la función gethostname de libc (u obtiene ComputerName en Windows) y se la devuelve como una cadena.
https://github.com/mattsheppard/gethostname4j
fuente
fuente
Solo una línea ... multiplataforma (Windows-Linux-Unix-Mac (Unix)) [Siempre funciona, no se requiere DNS]:
¡Ya terminaste!
fuente
InetAddress.getLocalHost (). GetHostName () es la mejor manera de salir de los dos, ya que esta es la mejor abstracción a nivel de desarrollador.
fuente