这听起来像以前应该问过的东西,而且它有一些,但是我希望获得机器的本地主机名和IP地址,即使它无法通过DNS解析(在Java中)。
我可以通过迭代NetworkInterfaces.getNetworkInterfaces()
来获取没有解决方案的本地IP地址。
我发现这个问题的任何答案都表明要使用getLocalHost()
InetAddress localhost = java.net.InetAddress.getLocalHost();
hostName = localhost.getHostName();
但如果主机名无法通过DNS解析,则会抛出UnknownHostException
。
如果没有在幕后进行DNS查找,是否无法获取本地主机名?
编辑:检索到的IP地址为10.4.168.23
例外是java.net.UnknownHostException: cms1.companyname.com: cms1.companyname.com
(主机名已更改为伪匿名),并且hosts文件不包含主机名。但它知道它的主机名,所以我不确定为什么我不能在没有抛出异常的情况下得到它。
答案 0 :(得分:12)
是的, 应该在Java中获取主机名而不需要使用名称服务查找,但遗憾的是没有。
但是,您可以这样做:
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
}
}
这将使您在传统的Sun JDK平台(Windows,Solaris,Linux)上获得100%的效果,但如果您的操作系统更加激动(从Java角度来看),则会变得不那么容易。请参阅代码示例中的注释。
我希望有更好的方法。
答案 1 :(得分:6)
这个问题很老,但不幸的是仍然有用,因为在Java中获取机器的主机名仍然不是一件容易的事。这是我在不同系统上进行一些测试的解决方案:
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() : "";
}
}
}
不同操作系统的结果:
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
这个有点奇怪,因为echo $HOSTNAME
返回正确的主机名,但System.getenv("HOSTNAME")
没有(这可能只是我环境的一个问题):
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
"
机器名称已被替换为(某些)匿名,但我保留了大写和结构。注意执行hostname
时的额外换行符,在某些情况下可能需要考虑它。
答案 2 :(得分:2)
或者,使用JNA在unix上调用gethostname
函数,避免反向DNS查找。
一些注意事项:在Linux上,我相信gethostname
只需调用uname
并解析输出。在OS X上,情况更复杂,因为您的主机名可能会受到DNS的影响,但除了这些副作用之外,它绝对是我从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
包含Win32函数,所以它就像调用Kernel32Util.getComputerName()
一样简单。
答案 3 :(得分:1)
如果您获得127.0.0.1作为IP地址,那么您可能需要找到特定于操作系统的主机文件,并在其中添加映射到您的主机名。
答案 4 :(得分:1)
这有点像黑客。但您可以从Java启动新进程并运行hostname
命令。读取子进程的输出流将为您提供localhost的名称。
答案 5 :(得分:1)
如果没有配置DNS,Java将读取/ etc / hosts文件,或者更确切地说是相应的C函数。
答案 6 :(得分:0)
在Linux上阅读
/proc/sys/kernel/hostname
答案 7 :(得分:0)
如果您不反对使用来自maven central的外部依赖项,我写了gethostname4j来为我自己解决这个问题。它只是使用JNA来调用libc的gethostname函数(或在Windows上获取ComputerName)并将其作为字符串返回给你。
https://github.com/mattsheppard/gethostname4j
(我认为它几乎正是@ danny-thomas所提议的,但如果您已经使用Maven,可能会更方便;)