Хотя на эту тему уже дан ответ, есть еще что сказать.
Прежде всего: очевидно, нам нужны некоторые определения здесь.InetAddress.getLocalHost().getHostName()
дает вам имя хоста с точки зрения сети .Проблемы с этим подходом хорошо документированы в других ответах: он часто требует поиска DNS, он неоднозначен, если у хоста несколько сетевых интерфейсов, и иногда он просто терпит неудачу (см. Ниже).
Но на любой ОСесть и другое имя.Имя хоста, которое определяется очень рано в процессе загрузки, задолго до инициализации сети.Windows называет это имя_компьютера , Linux называет его имя хоста ядра , а Solaris использует слово имя узла .Мне больше всего нравится слово имя_компьютера , поэтому теперь я буду использовать это слово.
Поиск имени компьютера
В Linux / Unixcomputername - это то, что вы получаете из функции C gethostname()
, или hostname
, команда из оболочки или HOSTNAME
переменная окружения в Bash-подобных оболочках.
В Windows имя компьютера - это то, чтовы получаете из переменной окружения COMPUTERNAME
или функцию Win32 GetComputerName
.
У Java нет способа получить то, что я определил как 'имя_компьютера'. КонечноСуществуют обходные пути, описанные в других ответах, например, для Windows, вызывающей System.getenv("COMPUTERNAME")
, но в Unix / Linux нет хорошего обходного пути, не прибегая к JNI / JNA или Runtime.exec()
.Если вы не возражаете против решения JNI / JNA, тогда есть gethostname4j , который очень прост и очень прост в использовании.
Давайте продолжим с двумя примерами, один из Linux и один из Solaris., которые демонстрируют, как вы можете легко попасть в ситуацию, когда вы не можете получить имя компьютера, используя стандартные методы Java.
Пример Linux
Во вновь созданной системе, где хост во время установки был названкак 'chicago', мы теперь изменим так называемое имя хоста ядра:
$ hostnamectl --static set-hostname dallas
Теперь имя хоста ядра - 'dallas', как видно из команды hostname:
$ hostname
dallas
Ноу нас все еще есть
$ cat /etc/hosts
127.0.0.1 localhost
127.0.0.1 chicago
В этом нет неправильной конфигурации.Это просто означает, что сетевое имя хоста (или, скорее, имя интерфейса обратной связи) отличается от имени компьютера хоста.
Теперь попробуйте выполнить InetAddress.getLocalHost().getHostName()
, и он выдаст исключение java.net.UnknownHostException.Вы в основном застряли.Невозможно получить ни значение «dallas», ни значение «chicago».
Пример Solaris
Пример ниже основан на Solaris 11.3.
Хост имеетнамеренно настроен так, чтобы имя петлевого имени <> nodename.
Другими словами, у нас было:
$ svccfg -s system/identity:node listprop config
...
...
config/loopback astring chicago
config/nodename astring dallas
и содержимое / etc / hosts:
:1 chicago localhost
127.0.0.1 chicago localhost loghost
и результат команды hostname будет такой:
$ hostname
dallas
Как и в примере с Linux, вызов InetAddress.getLocalHost().getHostName()
завершится неудачно с
java.net.UnknownHostException: dallas: dallas: node name or service name not known
Так же, как пример с Linux, который высейчас застряли.Нет никакого способа получить ни значение «dallas», ни значение «chicago».
Когда вы действительно будете с этим бороться?
Очень часто вы обнаружите, что InetAddress.getLocalHost().getHostName()
действительно будетвернуть значение, равное имени компьютера.Так что проблем нет (за исключением дополнительных накладных расходов на разрешение имен).
Проблема обычно возникает в средах PaaS, где существует разница между именем компьютера и именем интерфейса обратной связи.Например, люди сообщают о проблемах в Amazon EC2.
Отчеты об ошибках / RFE
Небольшой поиск показывает этот отчет RFE: link1 , link2 .Однако, судя по комментариям к этому отчету, команда JDK, по-видимому, в значительной степени неправильно поняла проблему, поэтому вряд ли она будет решена.
Мне нравится сравнение в RFE с другими языками программирования.