Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java8中,如何在不在环境中硬编码的情况下获取主机名?_Java_Linux_Spring_Java 8_Hostname - Fatal编程技术网

在Java8中,如何在不在环境中硬编码的情况下获取主机名?

在Java8中,如何在不在环境中硬编码的情况下获取主机名?,java,linux,spring,java-8,hostname,Java,Linux,Spring,Java 8,Hostname,我们刚刚在AmazonLinux上升级到Java8。我们使用的是Spring 4.3.8.0版本。过去,我们可以通过在应用程序上下文文件中设置bean来获取机器主机名,如下所示 <bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" /> <bean id="hostname" factory-bean="localhostInetAddress" fa

我们刚刚在AmazonLinux上升级到Java8。我们使用的是Spring 4.3.8.0版本。过去,我们可以通过在应用程序上下文文件中设置bean来获取机器主机名,如下所示

<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />
在Java8之前,它通常包含在命令行上运行的“hostname”值,即

[myuser@machine1 ~]$ hostname
machine1.mydomain.org
如何重新配置bean,使其获得命令行列出的主机名?我不想在任何地方硬编码任何内容。

来自:

JDK中也有类似的错误

据我所知,他们改变了默认的解决过程

它们支持/etc/nsswitch.conf中的配置,其中主机是为/etc/hosts配置的,为名称解析提供了主要优先级

通常/etc/hosts有127.0.0.1 localhost的记录,该记录提供了主机localhost的名称


您可以尝试
InetAddress.getCanonicalHostName()

getCanonicalHostName()的JavaDocs说

获取此IP地址的完全限定域名。尽力而为方法,这意味着我们可能无法根据基础系统配置返回FQDN


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

  • 实际使用运行hostname命令。它相当便携,几乎可以在任何地方使用。(可能不在IBM的大型机上)
  • 获取所有可用的网络接口并获取它们的主机名
  • 将环境或系统属性设置为主机名的值。
    比如java-Dmy.hostname=
    hostname
  • 可悲的是,在SpringXML中它并没有那么简单

    已知所有其他选项都能提供不同程度的精度。
    如127.0.0.1可能会解析为localhost或localhost.localdomain。

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

    我相信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()">
    
    
    

    请查看结果是否不符合您的需要。

    我最好在.properties文件中为类似主机名的内容定义一个属性

    hostname=myserver.mydomain.com
    

    并在应用程序中使用它。这条路不需要编码。它还避免了对操作系统配置的依赖,这些配置可以在不引起注意的情况下进行更改。

    Java8中的InetAddress对主机名的解析有很大的影响。该错误在8u20版本中被报告,并从那时起被修复。请检查您是否不在此版本上。如果不是,则使用
    InetAddress.getLocalHost().getHostName()
    将获得主机名

    我还建议在AWS实例上设置一个

  • 更新/etc/hosts
  • 更新/etc/hostname
  • 运行
    hostname
    检查主机名
  • 重新启动并检查持久主机名
  • 如果需要,这将允许您从文件中读取主机名

    另外,如果
    hostname
    命令给出了正确的结果,则使用执行该命令并读取输入流以获得响应


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

    中有一个类似的问题

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

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

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

    您始终可以使用该类进行以下操作:

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

    但这并不是你所能推荐的那样

    你有运行安全管理器吗?From:“如果不允许该操作,则返回表示环回地址的InetAddress。”您还可以尝试使用
    getCanonicalHostName()
    来获取fqn,而不是
    getHostName()
    您是指Java 8的安全管理器吗?我的意思是,如果存在某种Linux安全管理器,那么无论Java版本如何,它都不允许您所说的操作,对吗?我想,文档中特别提到Java端安全管理器,但当然,操作系统端的限制也会影响结果。但目前还不清楚Java API是否能保证这种情况下的特定行为……我之所以这样问,是因为它可能不会是操作系统,否则我以前对Java 8之前版本的调用就不会起作用。你知道我希望Java端安全管理器在哪里吗?@Holger嗯,我在代码中看到的注释实际上是
    exec(hostname)
    。。。它们还声明在Amazon上
    InetAddress.getLocalHost()
    返回(有时)环回设备,即
    localhost
    。我可能需要ping这些行的作者以了解实际发生的情况。如果我更改/etc/hosts文件,不会影响Linux系统上的其他内容吗?如果答案是“是”或“可能”,我更愿意使用一个与我的Java webapp/app容器隔离的解决方案。嘿,如果你的建议与Holger在评论中的建议相同,我尝试了taht,但没有成功。我的开发环境是一台Mac High Sierra机器。在那种环境下,上面的方法还能工作吗?当然不能,因为信息是从EC2 rest服务检索的。但是您肯定有一个spring测试配置文件,您可以在其中设置字符串值。我不希望域被硬编码。它已经存在于系统中。为什么我不能从这里开始呢?您的主机名配置是基于环境变量的。JVM 8+版本
    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);
    }