在Java 8中,如何在不在我的环境中对其进行硬编码的情况下获取主机名?

时间:2022-01-14 07:33:16

We just upgraded to Java 8 on Amazon Linux. We are using Spring 4.3.8.RELEASE. It used to be that we could get our machine hostname by setting up beans in our application context file like so ...

我们刚刚在Amazon 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" />

But with Java 8, the bean "hostname" now contains the string

但是对于Java 8,bean“hostname”现在包含字符串

localhost

Before Java 8, it used to contain the "hostname" value as run on the command line, which is

在Java 8之前,它曾用于包含在命令行上运行的“hostname”值,即

[myuser@machine1 ~]$ hostname
machine1.mydomain.org

How can I reconfigure our bean so that it gets the hostname that the command line lists out? I don't want to hard-code anything anywhere.

如何重新配置​​我们的bean,以便它获取命令行列出的主机名?我不想在任何地方硬编码。

9 个解决方案

#1


0  

There are a similar question in the OpenJDK bugs

OpenJDK中有一个类似的问题

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.

较新的调用遵循localhosts /etc/nsswitch.conf配置文件。对于这台机器,该文件告诉这些调用在引用其他命名服务之前查看文件。

Since the /etc/hosts file contains an explicit mapping for this hostname / IP combination, that is what is returned.

由于/ etc / hosts文件包含此主机名/ IP组合的显式映射,因此返回的内容。

In the older JDK's the gethostbyname actually ignored the local machines settings and immediately delegated to the naming service.

在较旧的JDK中,gethostbyname实际上忽略了本地计算机设置并立即委托给命名服务。

You can always use the Runtime class for that :

您始终可以使用Runtime类:

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);
}

But it's not so recommended as you can see

但是你不能这么推荐

#2


4  

From InetAddress java 8 is not getting the hostname :

从InetAddress java 8获取主机名:

There was similar bug fired in JDK.

在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.

他们尊重/etc/nsswitch.conf中的配置,其中为/ etc / hosts配置了主机,为其提供了名称解析的主要优先级。

Usually /etc/hosts has record for 127.0.0.1 localhost that provide name for host localhost

通常/ etc / hosts具有为主机localhost提供名称的127.0.0.1 localhost记录

#3


2  

You could try InetAddress.getCanonicalHostName()

你可以尝试InetAddress.getCanonicalHostName()

The JavaDocs for getCanonicalHostName() says

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.

获取此IP地址的完全限定域名。尽力而为方法,这意味着我们可能无法返回FQDN,具体取决于底层系统配置。

#4


2  

You really have three options of differing complexity and information value:

您确实有三种不同的复杂性和信息价值选择:

  1. Actually run the hostname command using Runtime. It's fairly portable and should work pretty much everywhere. (Maybe not on IBM's Mainframes)
  2. 实际上使用Runtime运行hostname命令。它相当便携,几乎可以在任何地方使用。 (可能不在IBM的大型机上)
  3. Grab all available network interfaces and get their hostnames. https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  4. 获取所有可用的网络接口并获取其主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  5. Set an environment or system property as the value of hostname.
    Like java -Dmy.hostname=hostname ...
  6. 将环境或系统属性设置为hostname的值。像java -Dmy.hostname = hostname ...

Sad part is that it's not that straightforward in Spring XML.

可悲的是,它在Spring XML中并不那么简单。

All other options are known to give varying degrees of accuracy. Like 127.0.0.1 will likely resolve to localhost or localhost.localdomain.

众所周知,所有其他选项都具有不同程度的准确性。像127.0.0.1可能会解析为localhost或localhost.localdomain。

#5


2  

Alternatively, you can run the hostname linux command using Java Runtime, code should be something like below:

或者,您可以使用Java Runtime运行hostname 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();

#6


2  

Since my comment got lost in the stream, please try

由于我的评论在流中丢失了,请尝试

<bean id="hostname" class="com.amazonaws.util.EC2MetadataUtils" factory-method="getLocalHostName()">

Have a look at Amazon's documemtation if the result does not suits your needs.

如果结果不符合您的需求,请查看亚马逊的文档。

#7


2  

I can be better to define a property in your .properties file for hostname like.

我可以更好地在.properties文件中为hostname定义一个属性。

hostname=myserver.mydomain.com

And use it in your application. This way is not harcoded. It also avoid dependency to operating system config which can be changed without attention.

并在您的应用程序中使用它。这种方式没有被编码。它还避免了对操作系统配置的依赖,操作系统配置可以在不注意的情

#8


2  

InetAddress in Java 8 had a bug regarding the resolution of hostname. The bug was reported in version 8u20 and has been fixed since then. Please check that you are not on this version. If not, then using InetAddress.getLocalHost().getHostName() will give you the hostname.

Java 8中的InetAddress有关于主机名解析的错误。该错误在版本8u20中报告,并且从那时起已经修复。请检查您是否使用此版本。如果没有,那么使用InetAddress.getLocalHost()。getHostName()将为您提供主机名。

Also I suggest, setting up a static hostname on the AWS instance.

我还建议在AWS实例上设置静态主机名。

  1. Update /etc/hosts
  2. 更新/ etc / hosts
  3. Update /etc/hostname
  4. 更新/ etc / hostname
  5. Run hostname to check the hostname
  6. 运行hostname以检查主机名
  7. Reboot and check the persisted hostname
  8. 重新启动并检查持久化的主机名

This should allow you to read the hostname from the file if required.

这应该允许您在需要时从文件中读取主机名。

Also, if hostname command is giving the correct result, then use exec method in Runtime class to execute the command and the read the InputStream to get the response.

此外,如果hostname命令给出正确的结果,则在Runtime类中使用exec方法执行命令并读取InputStream以获取响应。

PS: You can use InetAddress.getLocalHost().isLoopbackAddress() to check whether the address is a LoopbackAddress and then use a fallback method.

PS:您可以使用InetAddress.getLocalHost()。isLoopbackAddress()来检查地址是否为LoopbackAddress,然后使用回退方法。

#9


2  

I believe Java still calls the native gethostname(), but couldn't say why this fails.

我相信Java仍然会调用本机gethostname(),但不能说为什么会失败。

For Linux, you could try this alternative:

对于Linux,您可以尝试这种替代方案:

String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);

#1


0  

There are a similar question in the OpenJDK bugs

OpenJDK中有一个类似的问题

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.

较新的调用遵循localhosts /etc/nsswitch.conf配置文件。对于这台机器,该文件告诉这些调用在引用其他命名服务之前查看文件。

Since the /etc/hosts file contains an explicit mapping for this hostname / IP combination, that is what is returned.

由于/ etc / hosts文件包含此主机名/ IP组合的显式映射,因此返回的内容。

In the older JDK's the gethostbyname actually ignored the local machines settings and immediately delegated to the naming service.

在较旧的JDK中,gethostbyname实际上忽略了本地计算机设置并立即委托给命名服务。

You can always use the Runtime class for that :

您始终可以使用Runtime类:

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);
}

But it's not so recommended as you can see

但是你不能这么推荐

#2


4  

From InetAddress java 8 is not getting the hostname :

从InetAddress java 8获取主机名:

There was similar bug fired in JDK.

在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.

他们尊重/etc/nsswitch.conf中的配置,其中为/ etc / hosts配置了主机,为其提供了名称解析的主要优先级。

Usually /etc/hosts has record for 127.0.0.1 localhost that provide name for host localhost

通常/ etc / hosts具有为主机localhost提供名称的127.0.0.1 localhost记录

#3


2  

You could try InetAddress.getCanonicalHostName()

你可以尝试InetAddress.getCanonicalHostName()

The JavaDocs for getCanonicalHostName() says

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.

获取此IP地址的完全限定域名。尽力而为方法,这意味着我们可能无法返回FQDN,具体取决于底层系统配置。

#4


2  

You really have three options of differing complexity and information value:

您确实有三种不同的复杂性和信息价值选择:

  1. Actually run the hostname command using Runtime. It's fairly portable and should work pretty much everywhere. (Maybe not on IBM's Mainframes)
  2. 实际上使用Runtime运行hostname命令。它相当便携,几乎可以在任何地方使用。 (可能不在IBM的大型机上)
  3. Grab all available network interfaces and get their hostnames. https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  4. 获取所有可用的网络接口并获取其主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  5. Set an environment or system property as the value of hostname.
    Like java -Dmy.hostname=hostname ...
  6. 将环境或系统属性设置为hostname的值。像java -Dmy.hostname = hostname ...

Sad part is that it's not that straightforward in Spring XML.

可悲的是,它在Spring XML中并不那么简单。

All other options are known to give varying degrees of accuracy. Like 127.0.0.1 will likely resolve to localhost or localhost.localdomain.

众所周知,所有其他选项都具有不同程度的准确性。像127.0.0.1可能会解析为localhost或localhost.localdomain。

#5


2  

Alternatively, you can run the hostname linux command using Java Runtime, code should be something like below:

或者,您可以使用Java Runtime运行hostname 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();

#6


2  

Since my comment got lost in the stream, please try

由于我的评论在流中丢失了,请尝试

<bean id="hostname" class="com.amazonaws.util.EC2MetadataUtils" factory-method="getLocalHostName()">

Have a look at Amazon's documemtation if the result does not suits your needs.

如果结果不符合您的需求,请查看亚马逊的文档。

#7


2  

I can be better to define a property in your .properties file for hostname like.

我可以更好地在.properties文件中为hostname定义一个属性。

hostname=myserver.mydomain.com

And use it in your application. This way is not harcoded. It also avoid dependency to operating system config which can be changed without attention.

并在您的应用程序中使用它。这种方式没有被编码。它还避免了对操作系统配置的依赖,操作系统配置可以在不注意的情

#8


2  

InetAddress in Java 8 had a bug regarding the resolution of hostname. The bug was reported in version 8u20 and has been fixed since then. Please check that you are not on this version. If not, then using InetAddress.getLocalHost().getHostName() will give you the hostname.

Java 8中的InetAddress有关于主机名解析的错误。该错误在版本8u20中报告,并且从那时起已经修复。请检查您是否使用此版本。如果没有,那么使用InetAddress.getLocalHost()。getHostName()将为您提供主机名。

Also I suggest, setting up a static hostname on the AWS instance.

我还建议在AWS实例上设置静态主机名。

  1. Update /etc/hosts
  2. 更新/ etc / hosts
  3. Update /etc/hostname
  4. 更新/ etc / hostname
  5. Run hostname to check the hostname
  6. 运行hostname以检查主机名
  7. Reboot and check the persisted hostname
  8. 重新启动并检查持久化的主机名

This should allow you to read the hostname from the file if required.

这应该允许您在需要时从文件中读取主机名。

Also, if hostname command is giving the correct result, then use exec method in Runtime class to execute the command and the read the InputStream to get the response.

此外,如果hostname命令给出正确的结果,则在Runtime类中使用exec方法执行命令并读取InputStream以获取响应。

PS: You can use InetAddress.getLocalHost().isLoopbackAddress() to check whether the address is a LoopbackAddress and then use a fallback method.

PS:您可以使用InetAddress.getLocalHost()。isLoopbackAddress()来检查地址是否为LoopbackAddress,然后使用回退方法。

#9


2  

I believe Java still calls the native gethostname(), but couldn't say why this fails.

我相信Java仍然会调用本机gethostname(),但不能说为什么会失败。

For Linux, you could try this alternative:

对于Linux,您可以尝试这种替代方案:

String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);