[英]How do I get the local hostname if unresolvable through DNS in Java?
這聽起來像以前應該問過的東西,它有一些,但我希望獲得機器的本地主機名和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文件不包含主機名。 但它確實知道它的主機名,所以我不知道為什么我不能在沒有拋出異常的情況下得到它。
是的,在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角度來看),則會變得不那么容易。 請參閱代碼示例中的注釋。
我希望有更好的方法。
這個問題很老,但不幸的是仍然有用,因為用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
時的額外換行符,在某些情況下可能需要考慮它。
或者,使用JNA在unixes上調用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()
一樣簡單。
如果沒有配置DNS,或者相應的C函數將會讀取/ etc / hosts文件。
如果您獲得127.0.0.1作為IP地址,則可能需要找到特定於操作系統的主機文件,並在其中添加映射到主機名。
這有點像黑客。 但您可以從Java啟動新進程並運行hostname
命令。 讀取子進程的輸出流將為您提供localhost的名稱。
在Linux上閱讀
/proc/sys/kernel/hostname
如果你不反對使用maven central的外部依賴,我寫了gethostname4j來解決這個問題。 它只是使用JNA調用libc的gethostname函數(或在Windows上獲取ComputerName)並將其作為字符串返回給您。
https://github.com/mattsheppard/gethostname4j
(我認為這幾乎正是@ danny-thomas所提議的,但如果你已經在使用Maven,可能會更方便;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.