In Java 8, how do I get my hostname without hard-coding it in my environment?

好久不见. 提交于 2019-12-09 07:46:30

问题


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

<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

localhost

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

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


回答1:


There are a similar question in the OpenJDK bugs

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.

You can always use the Runtime class for that :

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:


From 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




回答3:


You could try InetAddress.getCanonicalHostName()

The JavaDocs for getCanonicalHostName() says

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.




回答4:


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. Grab all available network interfaces and get their hostnames. https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  3. Set an environment or system property as the value of hostname.
    Like java -Dmy.hostname=hostname ...

Sad part is that it's not that straightforward in 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.




回答5:


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

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:


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:


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

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:


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.

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

  1. Update /etc/hosts
  2. Update /etc/hostname
  3. Run hostname to check the hostname
  4. Reboot and check the persisted hostname

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.

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




回答9:


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

For Linux, you could try this alternative:

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


来源:https://stackoverflow.com/questions/48325178/in-java-8-how-do-i-get-my-hostname-without-hard-coding-it-in-my-environment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!