2011-05-18 16 views
13

Esto suena como algo que debería haberse preguntado antes, y tiene una especie de, pero estoy tratando de obtener el nombre de host local y las direcciones IP de una máquina, incluso cuando no se puede resolver a través de DNS (en Java).¿Cómo obtengo el nombre de host local si no se puede resolver a través de DNS en Java?

Puedo obtener las direcciones IP locales sin resolución al iterar a través de NetworkInterfaces.getNetworkInterfaces().

Cualquier respuesta a esta pregunta que he encontrado indican que se use getLocalHost()

InetAddress localhost = java.net.InetAddress.getLocalHost(); 
hostName = localhost.getHostName(); 

pero esto arroja una UnknownHostException si el nombre de host no se puede resolver a través de DNS.

¿No hay forma de obtener el nombre de host local sin una búsqueda de DNS que ocurra detrás de escena?

edición: la dirección de IP recuperada es 10.4.168.23 La excepción es java.net.UnknownHostException: cms1.companyname.com: cms1.companyname.com (nombre de host cambió para pseudo-anonimato), y el archivo hosts no contiene el nombre de host. Pero hace saber su nombre de host, así que no estoy seguro de por qué no puedo obtenerlo sin una excepción.

Respuesta

1

Si obtiene 127.0.0.1 como la dirección IP, puede que necesite ubicar el archivo de hosts específico del sistema operativo y agregar una asignación a su nombre de host.

+0

El sistema operativo conoce el nombre de host, como cuando llamo getLocalHost (), arroja una excepción que contiene el nombre de host. Solo quiero poder obtener ese nombre de host sin una búsqueda. –

+0

Asegúrate de que tu nombre de host no contenga caracteres de subrayado. Si está en Windows, no le impedirá utilizar guiones bajos en el nombre de host, pero no funciona con Java debido a la estricta verificación de los caracteres permitidos. – sinha

1

Esto es un poco hackeo. Pero podría lanzar un nuevo Proceso desde Java y ejecutar el comando hostname. La lectura de la salida del proceso secundario le daría el nombre del localhost.

+0

Pensé en esto también, pero esperaba una mejor solución. –

11

Sí, hay debería ser ser una forma en Java para obtener el nombre de host sin recurrir a las búsquedas de servicios de nombres, pero desafortunadamente no lo es.

Sin embargo, se puede hacer algo como esto:

if (System.getProperty("os.name").startsWith("Windows")) { 
    // Windows will always set the 'COMPUTERNAME' variable 
    return System.getenv("COMPUTERNAME"); 
} else { 
    // If it is not Windows then it is most likely a Unix-like operating system 
    // such as Solaris, AIX, HP-UX, Linux or MacOS. 

    // Most modern shells (such as Bash or derivatives) sets the 
    // HOSTNAME variable so lets try that first. 
    String hostname = System.getenv("HOSTNAME"); 
    if (hostname != null) { 
     return hostname; 
    } else { 

     // If the above returns null *and* the OS is Unix-like 
     // then you can try an exec() and read the output from the 
     // 'hostname' command which exist on all types of Unix/Linux. 

     // If you are an OS other than Unix/Linux then you would have 
     // to do something else. For example on OpenVMS you would find 
     // it like this from the shell: F$GETSYI("NODENAME") 
     // which you would probably also have to find from within Java 
     // via an exec() call. 

     // If you are on zOS then who knows ?? 

     // etc, etc 
    } 
} 

y que recibirá el 100% de lo que desea en las plataformas Sun JDK tradicionales (Windows, Solaris, Linux), pero se vuelve menos fácil si su sistema operativo es más excótico (desde una perspectiva de Java). Ver los comentarios en el ejemplo de código.

Ojalá hubiera una mejor manera.

+0

No obtengo 'HOSTNAME' cuando Tomcat es un servicio de rc.d bajo FreeBSD, desafortunadamente. – lapo

+0

@lapo. No es un problema de Java. Deberá comprender su caparazón: ¿cuándo se establece la variable de entorno 'HOSTNAME'? Probablemente obtendrá una buena respuesta si pregunta en un foro de Unix/Linux algo como: * "Variable de entorno HOSTNAME no definido. ¿Por qué?" *. – peterh

+0

no es un problema de Java, pero estar disponible por defecto es una cosa; si debo cambiar los valores predeterminados del sistema, también podría definir correctamente en '127.0.0.1' en'/etc/host' (que de todos modos es una buena regla). Al final usé 'HOSTNAME' else' COMUTERNAME' else 'getLocalHost()'. – lapo

1

Java leerá el archivo/etc/hosts si no hay DNS configurado, o más bien las funciones C correspondientes.

5

Esta pregunta es antigua, pero desafortunadamente sigue siendo relevante ya que todavía no es trivial obtener el nombre de host de una máquina en Java. Aquí está mi solución con un poco de pruebas de funcionamiento en diferentes sistemas:

public static void main(String[] args) throws IOException { 
     String OS = System.getProperty("os.name").toLowerCase(); 

     if (OS.indexOf("win") >= 0) { 
      System.out.println("Windows computer name throguh env:\"" + System.getenv("COMPUTERNAME") + "\""); 
      System.out.println("Windows computer name through exec:\"" + execReadToString("hostname") + "\""); 
     } else { 
      if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0) { 
       System.out.println("Linux computer name throguh env:\"" + System.getenv("HOSTNAME") + "\""); 
       System.out.println("Linux computer name through exec:\"" + execReadToString("hostname") + "\""); 
       System.out.println("Linux computer name through /etc/hostname:\"" + execReadToString("cat /etc/hostname") + "\""); 
      } 
     } 
    } 

    public static String execReadToString(String execCommand) throws IOException { 
     Process proc = Runtime.getRuntime().exec(execCommand); 
     try (InputStream stream = proc.getInputStream()) { 
      try (Scanner s = new Scanner(stream).useDelimiter("\\A")) { 
       return s.hasNext() ? s.next() : ""; 
      } 
     } 
    } 

Resultados para diferentes sistemas operativos:

OpenSuse 13,1

Linux computer name throguh env:"machinename" 
Linux computer name through exec:"machinename 
" 
Linux computer name through /etc/hostname:"" 

Ubuntu 14.04 LTS Éste es un poco extraño, ya que echo $HOSTNAME devuelve el nombre de host correcto, pero System.getenv("HOSTNAME") no (esto, sin embargo podría ser un problema sólo con mi entorno):

Linux computer name throguh env:"null" 
Linux computer name through exec:"machinename 
" 
Linux computer name through /etc/hostname:"machinename 
" 

de Windows 7

Windows computer name throguh env:"MACHINENAME" 
Windows computer name through exec:"machinename 
" 

Los nombres de las máquinas se han reemplazado por (algunos) anonimización, pero he conservado las mayúsculas y la estructura. Tenga en cuenta la nueva línea adicional al ejecutar hostname, es posible que deba tenerlo en cuenta en algunos casos.

+0

Veo el mismo problema en Ubuntu 14.04 con la variable de entorno 'HOSTNAME'. No se está exportando a tareas iniciadas por el shell (bash). Ejecutar 'export HOSTNAME' resuelve el problema. – neuhaus

2

Como alternativa, use JNA para llamar a la función gethostname en unixes, evitando la búsqueda DNS inversa.

Algunas notas: en Linux, creo que gethostname simplemente llama a uname y analiza la salida. En OS X, la situación es más compleja, ya que su nombre de host puede verse afectado por DNS, pero aparte de esos efectos secundarios, es definitivamente lo que obtengo de hostname.

import com.sun.jna.LastErrorException 
import com.sun.jna.Library 
import com.sun.jna.Native 

... 

private static final C c = (C) Native.loadLibrary("c", C.class); 

private static interface C extends Library { 
    public int gethostname(byte[] name, int size_t) throws LastErrorException; 
} 

public String getHostName() { 
    byte[] hostname = new byte[256]; 
    c.gethostname(hostname, hostname.length) 
    return Native.toString(hostname) 
} 

jna-platform.jar incluye funciones de Win32, por lo que no es tan simple como una llamada a Kernel32Util.getComputerName().

+0

Mejor respuesta, ya que no depende de DNS. – jkschneider

0

en Linux leer

/proc/sys/kernel/hostname 
0

Si no está contra el uso de una dependencia externa del experto centrales, escribí gethostname4j para resolver este problema por mí mismo. Simplemente utiliza JNA para llamar a la función gethostname de libc (u obtiene ComputerName en Windows) y se lo devuelve como una cadena.

https://github.com/mattsheppard/gethostname4j

(creo que es casi exactamente lo que @ danny-Thomas propuso, pero tal vez más conveniente si usted ya está usando Maven;)

Cuestiones relacionadas