Qual das alternativas a seguir é a melhor e mais portátil maneira de obter o nome do host do computador atual em Java?
Runtime.getRuntime().exec("hostname")
vs
InetAddress.getLocalHost().getHostName()
Qual das alternativas a seguir é a melhor e mais portátil maneira de obter o nome do host do computador atual em Java?
Runtime.getRuntime().exec("hostname")
vs
InetAddress.getLocalHost().getHostName()
Respostas:
A rigor - você não tem escolha a não ser ligar para
hostname(1)
ou - no Unixgethostname(2)
. Este é o nome do seu computador. Qualquer tentativa de determinar o nome do host por um endereço IP como esteestá fadado a falhar em algumas circunstâncias:
Além disso, não confunda o nome de um endereço IP com o nome do host (hostname). Uma metáfora pode deixar mais claro:
Isso ilustra muito bem, eu acho.
A boa notícia é: o nome do host real geralmente não é necessário. Na maioria dos casos, qualquer nome que se resolva em um endereço IP nesse host será suficiente. (O estrangeiro pode entrar na cidade por Northgate, mas moradores úteis traduzem a parte "2ª esquerda".)
Se os casos de canto restantes você deve usar a definitiva fonte desta configuração - que é a função C
gethostname(2)
. Essa função também é chamada pelo programahostname
.fonte
InetAddress.getLocalHost().getHostName()
é a maneira mais portátil.exec("hostname")
realmente chama o sistema operacional para executar ohostname
comando.Aqui estão algumas outras respostas relacionadas ao SO:
EDIT: Você deve dar uma olhada na resposta da AH ou na resposta de Arnout Engelen para obter detalhes sobre por que isso pode não funcionar como o esperado, dependendo da sua situação. Como resposta para essa pessoa que solicitou especificamente o portátil, ainda acho que
getHostName()
está bem, mas eles trazem alguns bons pontos que devem ser considerados.fonte
InetAddress.getLocalHost()
em alguns casos, retorna o dispositivo de loopback. Nesse caso,getHostName()
retorna "localhost", o que não é muito útil.Como outros observaram, a obtenção do nome do host com base na resolução do DNS não é confiável.
Como essa pergunta ainda é relevante em 2018 , gostaria de compartilhar com você minha solução independente de rede, com alguns testes em diferentes sistemas.
O código a seguir tenta fazer o seguinte:
No Windows
Leia a
COMPUTERNAME
variável de ambienteSystem.getenv()
.Execute
hostname.exe
e leia a respostaNo Linux
Leia a
HOSTNAME
variável de ambiente através deSystem.getenv()
Execute
hostname
e leia a respostaRead
/etc/hostname
(para fazer isso, estou executando,cat
já que o trecho já contém código para executar e ler. Porém, basta ler o arquivo).O código:
Resultados para diferentes sistemas operacionais:
macOS 10.13.2
OpenSuse 13.1
Ubuntu 14.04 LTS Este é meio estranho, pois
echo $HOSTNAME
retorna o nome de host correto, masSystem.getenv("HOSTNAME")
não:EDIT: De acordo com legolas108 ,
System.getenv("HOSTNAME")
funciona no Ubuntu 14.04 se você executarexport HOSTNAME
antes de executar o código Java.Windows 7
Windows 10
Os nomes das máquinas foram substituídos, mas mantive a capitalização e a estrutura. Observe a nova linha extra ao executar
hostname
, talvez seja necessário levar isso em consideração em alguns casos.fonte
export HOSTNAME
antes de executar o código Java no Ubuntu 14.04 LTS, ele também será retornado porSystem.getenv("HOSTNAME")
.export HOSTNAME
para o Java usá-lo? Eu pensei que deveria ser um padrão var var como PATH.\A
delimitador, é apenas um truque para ler todo o InputStream usando aScanner
.InetAddress.getLocalHost().getHostName()
é melhor (como explicado por Nick), mas ainda não é muito bomUm host pode ser conhecido sob vários nomes de host diferentes. Geralmente, você procurará o nome do host que seu host possui em um contexto específico.
Por exemplo, em um aplicativo Web, você pode estar procurando o nome do host usado por quem emitiu a solicitação que você está manipulando no momento. A melhor maneira de descobrir que isso depende de qual estrutura você está usando para seu aplicativo da web.
Em algum tipo de outro serviço voltado para a Internet, você deseja que o nome do host esteja disponível através do 'fora'. Devido a proxies, firewalls, etc., pode até não ser um nome de host na máquina em que o serviço está instalado - você pode tentar obter um padrão razoável, mas definitivamente deve configurá-lo para quem o instalar.
fonte
Embora este tópico já tenha sido respondido, há mais a dizer.
Primeiro de tudo: Claramente, precisamos de algumas definições aqui. O
InetAddress.getLocalHost().getHostName()
fornece o nome do host como visto da perspectiva da rede . Os problemas com essa abordagem estão bem documentados nas outras respostas: geralmente requer uma pesquisa de DNS, é ambíguo se o host tiver várias interfaces de rede e simplesmente falhar algumas vezes (veja abaixo).Mas em qualquer sistema operacional também existe outro nome. Um nome do host que é definido muito cedo no processo de inicialização, muito antes da inicialização da rede. O Windows se refere a isso como nome do computador , o Linux chama de nome do host do kernel e o Solaris usa a palavra nome do nó . Eu gosto mais da palavra nomedocomputador , então usarei essa palavra a partir de agora.
Localizando o nome do computador
No Linux / Unix, o nome do computador é o que você obtém da função C
gethostname()
, ouhostname
comando do shell ouHOSTNAME
variável de ambiente nos shells do tipo Bash.No Windows, o nome do computador é o que você obtém da variável de ambiente
COMPUTERNAME
ou daGetComputerName
função Win32 .Java não tem como obter o que defini como 'computername'. Claro, existem soluções alternativas, conforme descrito em outras respostas, como para chamadas do Windows
System.getenv("COMPUTERNAME")
, mas no Unix / Linux não há uma boa solução alternativa sem recorrer ao JNI / JNA ouRuntime.exec()
. Se você não se importa com uma solução JNI / JNA, existe o gethostname4j que é simples e muito fácil de usar.Vamos seguir com dois exemplos, um do Linux e outro do Solaris, que demonstram como você pode facilmente entrar em uma situação em que não pode obter o nome do computador usando métodos Java padrão.
Exemplo de Linux
Em um sistema recém-criado, em que o host durante a instalação foi nomeado como 'chicago', agora alteramos o chamado nome do host do kernel:
Agora, o nome do host do kernel é 'dallas', como é evidente no comando hostname:
Mas ainda temos
Não há configuração incorreta nisso. Significa apenas que o nome da rede do host (ou melhor, o nome da interface de loopback) é diferente do nome do computador do host.
Agora, tente executar
InetAddress.getLocalHost().getHostName()
e ele lançará java.net.UnknownHostException. Você está basicamente preso. Não há como recuperar nem o valor 'dallas' nem o valor 'chicago'.Exemplo do Solaris
O exemplo abaixo é baseado no Solaris 11.3.
O host foi deliberadamente configurado para que o nome do loopback <> nodename.
Em outras palavras, temos:
e o conteúdo de / etc / hosts:
e o resultado do comando hostname seria:
Assim como no exemplo do Linux, uma chamada para
InetAddress.getLocalHost().getHostName()
falhará comAssim como no exemplo do Linux, você está preso agora. Não há como recuperar nem o valor 'dallas' nem o valor 'chicago'.
Quando você realmente lutará com isso?
Muitas vezes você descobrirá que
InetAddress.getLocalHost().getHostName()
realmente retornará um valor igual ao nome do computador. Portanto, não há problema (exceto a sobrecarga adicional da resolução de nomes).O problema geralmente ocorre em ambientes PaaS, nos quais há uma diferença entre o nome do computador e o nome da interface de loopback. Por exemplo, as pessoas relatam problemas no Amazon EC2.
Relatórios de erros / RFE
Um pouco de pesquisa revela este relatório do RFE: link1 , link2 . No entanto, a julgar pelos comentários nesse relatório, o problema parece ter sido amplamente mal compreendido pela equipe do JDK, portanto, é improvável que seja abordado.
Gosto da comparação no RFE com outras linguagens de programação.
fonte
As variáveis de ambiente também podem fornecer um meio útil -
COMPUTERNAME
no Windows,HOSTNAME
na maioria dos shells Unix / Linux modernos.Consulte: https://stackoverflow.com/a/17956000/768795
Estou usando esses métodos como "suplementares" para
InetAddress.getLocalHost().getHostName()
, como várias pessoas apontam, essa função não funciona em todos os ambientes.Runtime.getRuntime().exec("hostname")
é outro complemento possível. Nesta fase, eu não o usei.fonte
StringUtils
, é fornecido pelo projeto Apache commons-lang. É altamente recomendável usá-lo ou algo parecido.System.getenv("HOSTNAME")
saiu nulo no Mac via Beanshell para Java, masPATH
foi extraído ok. Eu também poderia fazerecho $HOSTNAME
no Mac, apenas System.getenv ("HOSTNAME") parece ter problema. Estranho.A maneira mais portátil de obter o nome do host do computador atual em Java é a seguinte:
fonte
Se você não é contra o uso de uma dependência externa da maven central, escrevi gethostname4j para resolver esse problema por conta própria. Ele apenas usa o JNA para chamar a função gethostname da libc (ou obtém o ComputerName no Windows) e a retorna como uma string.
https://github.com/mattsheppard/gethostname4j
fonte
fonte
Apenas uma linha ... multiplataforma (Windows-Linux-Unix-Mac (Unix)) [Sempre funciona, sem necessidade de DNS]:
Você Terminou !!
fonte
InetAddress.getLocalHost (). GetHostName () é a melhor saída dentre as duas, pois essa é a melhor abstração no nível do desenvolvedor.
fonte