在 Java 8 中,如何在不在我的环境中对主机名进行硬编码的情况下获取主机名?
In Java 8, how do I get my hostname without hard-coding it in my environment?
我们刚刚在亚马逊 Linux 上升级到 Java 8。我们正在使用 Spring 4.3.8.RELEASE。过去我们可以通过在我们的应用程序上下文文件中设置 bean 来获取我们的机器主机名,就像这样...
<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />
但是对于 Java 8,bean "hostname" 现在包含字符串
localhost
在Java8之前,它曾经在命令行中包含"hostname"值作为运行,即
[myuser@machine1 ~]$ hostname
machine1.mydomain.org
我如何重新配置我们的 bean 以便它获得命令行列出的主机名?我不想在任何地方硬编码任何东西。
来自 InetAddress java 8 is not getting the hostname :
There was similar bug fired in JDK.
What I understand is that they changed default resolution process.
They honor configuration in /etc/nsswitch.conf where hosts are configured for /etc/hosts that gives it main priority for name resolution.
Usually /etc/hosts has record for 127.0.0.1 localhost that provide name for host localhost
你可以试试InetAddress.getCanonicalHostName()
getCanonicalHostName() 的 JavaDocs 说
Gets the fully qualified domain name for this IP address. Best effort method, meaning we may not be able to return the FQDN depending on the underlying system configuration.
你真的有三个不同复杂性和信息价值的选项:
- 实际上 运行 hostname 命令使用 Runtime。它相当便携,几乎可以在任何地方使用。 (可能不在 IBM 的大型机上)
- 获取所有可用的网络接口并获取它们的主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
- 将环境或系统 属性 设置为 hostname 的值。
喜欢java -Dmy.hostname=hostname
...
可悲的是,Spring XML 并不是那么简单。
已知所有其他选项都会提供不同程度的准确度。
像 127.0.0.1 可能会解析为 localhost 或 localhost.localdomain.
或者,您可以使用 Java 运行时 运行 主机名 linux 命令,代码应如下所示:
String cmdResult="";
Runtime r = Runtime.getRuntime();
Process p = r.exec("hostname");
BufferedReader in = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
cmdResult += inputLine;
}
in.close();
我相信 Java 仍然会调用本机 gethostname()
,但无法说明为什么会失败。
对于 Linux,您可以尝试以下替代方法:
String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);
由于我的评论在流中丢失,请尝试
<bean id="hostname" class="com.amazonaws.util.EC2MetadataUtils" factory-method="getLocalHostName()">
如果结果不符合您的需要,请查看Amazon's documemtation。
我可以更好地在您的 .properties 文件中为主机名定义一个 属性。
hostname=myserver.mydomain.com
并在您的应用程序中使用它。这种方式没有硬编码。它还避免了对操作系统配置的依赖,无需注意即可更改。
InetAddress in Java 8 有一个关于主机名解析的 bug。该错误已在 8u20 版中报告,此后已得到修复。请检查您是否使用此版本。如果不是,则使用 InetAddress.getLocalHost().getHostName()
将为您提供主机名。
我还建议,在 AWS 实例上设置 static hostname。
- 更新/etc/hosts
- 更新/etc/hostname
- 运行
hostname
检查主机名
- 重新启动并检查持久化的主机名
这应该允许您在需要时从文件中读取主机名。
此外,如果 hostname
命令给出了正确的结果,则使用 exec method in Runtime class 执行命令并读取 InputStream 以获得响应。
PS:可以使用InetAddress.getLocalHost().isLoopbackAddress()
判断地址是否为LoopbackAddress,然后使用fallback方法
中也有类似的问题
The newer calls respect the localhosts /etc/nsswitch.conf configuration files. In the case of this machine that file tells these
calls to look in files before referencing other naming services.
Since the /etc/hosts file contains an explicit mapping for this
hostname / IP combination, that is what is returned.
In the older JDK's the gethostbyname actually ignored the local
machines settings and immediately delegated to the naming service.
您始终可以使用 Runtime
class 来做到这一点:
Process hostname = Runtime.getRuntime().exec("hostname");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(hostname.getInputStream()));
String s;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
但不是很推荐see
我们刚刚在亚马逊 Linux 上升级到 Java 8。我们正在使用 Spring 4.3.8.RELEASE。过去我们可以通过在我们的应用程序上下文文件中设置 bean 来获取我们的机器主机名,就像这样...
<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />
但是对于 Java 8,bean "hostname" 现在包含字符串
localhost
在Java8之前,它曾经在命令行中包含"hostname"值作为运行,即
[myuser@machine1 ~]$ hostname
machine1.mydomain.org
我如何重新配置我们的 bean 以便它获得命令行列出的主机名?我不想在任何地方硬编码任何东西。
来自 InetAddress java 8 is not getting the hostname :
There was similar bug fired in JDK.
What I understand is that they changed default resolution process.
They honor configuration in /etc/nsswitch.conf where hosts are configured for /etc/hosts that gives it main priority for name resolution.
Usually /etc/hosts has record for 127.0.0.1 localhost that provide name for host localhost
你可以试试InetAddress.getCanonicalHostName()
getCanonicalHostName() 的 JavaDocs 说
Gets the fully qualified domain name for this IP address. Best effort method, meaning we may not be able to return the FQDN depending on the underlying system configuration.
你真的有三个不同复杂性和信息价值的选项:
- 实际上 运行 hostname 命令使用 Runtime。它相当便携,几乎可以在任何地方使用。 (可能不在 IBM 的大型机上)
- 获取所有可用的网络接口并获取它们的主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
- 将环境或系统 属性 设置为 hostname 的值。
喜欢java -Dmy.hostname=hostname
...
可悲的是,Spring XML 并不是那么简单。
已知所有其他选项都会提供不同程度的准确度。 像 127.0.0.1 可能会解析为 localhost 或 localhost.localdomain.
或者,您可以使用 Java 运行时 运行 主机名 linux 命令,代码应如下所示:
String cmdResult="";
Runtime r = Runtime.getRuntime();
Process p = r.exec("hostname");
BufferedReader in = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
cmdResult += inputLine;
}
in.close();
我相信 Java 仍然会调用本机 gethostname()
,但无法说明为什么会失败。
对于 Linux,您可以尝试以下替代方法:
String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);
由于我的评论在流中丢失,请尝试
<bean id="hostname" class="com.amazonaws.util.EC2MetadataUtils" factory-method="getLocalHostName()">
如果结果不符合您的需要,请查看Amazon's documemtation。
我可以更好地在您的 .properties 文件中为主机名定义一个 属性。
hostname=myserver.mydomain.com
并在您的应用程序中使用它。这种方式没有硬编码。它还避免了对操作系统配置的依赖,无需注意即可更改。
InetAddress in Java 8 有一个关于主机名解析的 bug。该错误已在 8u20 版中报告,此后已得到修复。请检查您是否使用此版本。如果不是,则使用 InetAddress.getLocalHost().getHostName()
将为您提供主机名。
我还建议,在 AWS 实例上设置 static hostname。
- 更新/etc/hosts
- 更新/etc/hostname
- 运行
hostname
检查主机名 - 重新启动并检查持久化的主机名
这应该允许您在需要时从文件中读取主机名。
此外,如果 hostname
命令给出了正确的结果,则使用 exec method in Runtime class 执行命令并读取 InputStream 以获得响应。
PS:可以使用InetAddress.getLocalHost().isLoopbackAddress()
判断地址是否为LoopbackAddress,然后使用fallback方法
The newer calls respect the localhosts /etc/nsswitch.conf configuration files. In the case of this machine that file tells these calls to look in files before referencing other naming services.
Since the /etc/hosts file contains an explicit mapping for this hostname / IP combination, that is what is returned.
In the older JDK's the gethostbyname actually ignored the local machines settings and immediately delegated to the naming service.
您始终可以使用 Runtime
class 来做到这一点:
Process hostname = Runtime.getRuntime().exec("hostname");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(hostname.getInputStream()));
String s;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
但不是很推荐see