问题
This sounds like something that should have been asked before, and it has sort of, but I'm looking to get the local hostname and IP addresses of a machine even when it is not resolvable through DNS (in Java).
I can get the local IP addresses without resolution by iterating through NetworkInterfaces.getNetworkInterfaces()
.
Any answers to this question I've found indicate to use getLocalHost()
InetAddress localhost = java.net.InetAddress.getLocalHost();
hostName = localhost.getHostName();
but this throws an UnknownHostException
if the hostname isn't resolvable through DNS.
Is there no way to get the local hostname without a DNS lookup happening behind the scenes?
edit: the IP address retrieved is 10.4.168.23
The exception is java.net.UnknownHostException: cms1.companyname.com: cms1.companyname.com
(hostname changed for pseudo-anonymity), and the hosts file does not contain the hostname. But it does know its hostname, so I'm not sure why I can't get it without an exception being thrown.
回答1:
Yes, there should be a way in Java to get the hostname without resorting to name service lookups but unfortunately there isn't.
However, you can do something like this:
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
}
}
and that will get you 100% what you want on the traditional Sun JDK platforms (Windows, Solaris, Linux) but becomes less easy if your OS is more excotic (from a Java perspective). See the comments in the code example.
I wish there was a better way.
回答2:
This question is old, but unfortunately still relevant since it's still not trivial to get a machine's host name in Java. Here's my solution with some test runs on different systems:
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() : "";
}
}
}
Results for different operating systems:
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
This one is kinda strange since echo $HOSTNAME
returns the correct hostname, but System.getenv("HOSTNAME")
does not (this however might be an issue with my environment only):
Linux computer name throguh env:"null"
Linux computer name through exec:"machinename
"
Linux computer name through /etc/hostname:"machinename
"
Windows 7
Windows computer name throguh env:"MACHINENAME"
Windows computer name through exec:"machinename
"
The machine names have been replaced for (some) anonymization, but I've kept the capitalization and structure. Note the extra newline when executing hostname
, you might have to take it into account in some cases.
回答3:
Alternatively, use JNA to call the gethostname
function on unixes, avoiding the reverse DNS lookup.
Some notes: on Linux, I believe gethostname
simply calls uname
and parses the output. On OS X the situation is more complex, as your hostname can be affected by DNS, but those side-effects aside, it's definitely what I get from 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
includes Win32 functions, so there it's as simple as a call to Kernel32Util.getComputerName()
.
回答4:
If you are getting 127.0.0.1 as the IP address then you may need to locate your Operating System specific hosts file and add a mapping to your hostname in it.
回答5:
This is a bit of a hack. But you could launch a new Process from Java and run the hostname
command. Reading the outputstream of the child process would give you the name of the localhost.
回答6:
Java will read the /etc/hosts file if there is no DNS configured, or rather the corresponding C functions will.
回答7:
on Linux read
/proc/sys/kernel/hostname
回答8:
If you're not against using an external dependency from maven central, I wrote gethostname4j to solve this problem for myself. It just uses JNA to call libc's gethostname function (or gets the ComputerName on Windows) and returns it to you as a string.
https://github.com/mattsheppard/gethostname4j
(I think it's almost exactly what @danny-thomas proposed, but maybe more convenient if you're already using Maven ;)
来源:https://stackoverflow.com/questions/6050011/how-do-i-get-the-local-hostname-if-unresolvable-through-dns-in-java