В Java 8, как мне получить свое имя хоста без жесткого кодирования в моей среде?

Мы только что перешли на Java 8 на Amazon Linux. Мы используем Spring 4.3.8.RELEASE. Раньше считалось, что мы можем получить наше машинное имя, настроив beans в нашем файле контекста приложения так...

<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />

Но с Java 8 бит "hostname" теперь содержит строку

localhost

До Java 8 оно содержало значение "имя хоста", которое запускалось в командной строке, что

[[email protected] ~]$ hostname
machine1.mydomain.org

Как я могу переконфигурировать наш компонент, чтобы он получил имя хоста, которое выводится в командной строке? Я не хочу ничего жестко кодировать.

Ответ 1

Подобный вопрос возникает в ошибках OpenJDK

Новые вызовы уважают файлы конфигурации localhosts/etc/nsswitch.conf. В случае этой машины этот файл сообщает этим вызовам смотреть в файлы, прежде чем ссылаться на другие службы именования.

Поскольку файл /etc/hosts содержит явное сопоставление для этой комбинации имен хостов /IP, это то, что возвращается.

В старшем JDK gethostbyname фактически игнорировал параметры локальных компьютеров и сразу же делегировался службе именования.

Вы всегда можете использовать для этого класс 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);
}

Но это не так рекомендуется, как вы можете видеть

Ответ 2

Из InetAddress java 8 не получает имя хоста:

В JDK произошла аналогичная ошибка.

Я понимаю, что они изменили процесс разрешения по умолчанию.

Они соблюдают конфигурацию в /etc/nsswitch.conf, где хосты настроены для /etc/hosts, что дает ему основной приоритет для разрешения имен.

Обычно /etc/hosts имеет запись для 127.0.0.1 localhost, которые предоставляют имя для хоста localhost

Ответ 3

Вы можете попробовать InetAddress.getCanonicalHostName()

JavaDocs для getCanonicalHostName() говорит

Получает полное доменное имя для этого IP-адреса. Метод наилучших усилий, то есть мы не сможем вернуть полное доменное имя в зависимости от базовой конфигурации системы.

Ответ 4

У вас действительно есть три варианта различной сложности и информационной ценности:

  1. На самом деле запустите команду hostname с помощью Runtime. Он довольно портативный и должен работать практически везде. (Возможно, не на мэйнфреймах IBM)
  2. Возьмите все доступные сетевые интерфейсы и получите их имена хостов. https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  3. Задайте свойство среды или системы как значение имени хоста.
    Как java -Dmy.hostname = hostname...

Печальная часть заключается в том, что это не так просто в Spring XML.

Известно, что все другие варианты дают разную степень точности. Подобно 127.0.0.1, скорее всего, будет разрешено localhost или localhost.localdomain.

Ответ 5

Кроме того, вы можете запустить команду linux linux с использованием Java Runtime, код должен выглядеть примерно так:

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

Я считаю, что Java по-прежнему вызывает родное gethostname(), но не может сказать, почему это не удается.

Для Linux вы можете попробовать эту альтернативу:

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

Ответ 7

Поскольку мой комментарий потерялся в потоке, попробуйте

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

Посмотрите на документацию Amazon, если результат не соответствует вашим потребностям.

Ответ 8

Я могу лучше определить свойство в вашем файле.properties для имени хоста.

hostname=myserver.mydomain.com

И используйте его в своем приложении. Этот путь не кодируется. Это также позволяет избежать зависимости от конфигурации операционной системы, которая может быть изменена без внимания.

Ответ 9

InetAddress в Java 8 имел ошибку в отношении разрешения имени хоста. Об ошибке сообщалось в версии 8u20 и с тех пор исправлено. Убедитесь, что вы не используете эту версию. Если нет, то с помощью InetAddress.getLocalHost().getHostName() предоставит вам имя хоста.

Также я предлагаю настроить статическое имя хоста на экземпляре AWS.

  1. Обновить /etc/hosts
  2. Обновить /etc/hostname
  3. Запустить hostname чтобы проверить имя хоста
  4. Перезагрузите и проверьте сохраненное имя хоста

Это должно позволить вам прочитать имя хоста из файла, если это необходимо.

Кроме того, если команда hostname дает правильный результат, используйте метод exec в классе Runtime для выполнения команды и прочитайте InputStream, чтобы получить ответ.

PS: Вы можете использовать InetAddress.getLocalHost().isLoopbackAddress() чтобы проверить, является ли адрес LoopbackAddress, а затем использовать метод резервного копирования.