답변:
엄밀히 말하면- hostname(1)
또는 유닉스를 호출하는 것 외에는 선택의 여지가 없습니다 gethostname(2)
. 이것은 컴퓨터의 이름입니다. 이와 같은 IP 주소로 호스트 이름을 확인하려는 시도
InetAddress.getLocalHost().getHostName()
어떤 상황에서는 실패 할 것입니다 :
또한 IP 주소 이름과 호스트 이름 (호스트 이름)을 혼동하지 마십시오. 은유가 더 명확하게 만들 수 있습니다.
"런던"이라는 대도시 (서버)가 있습니다. 성벽 안에서 많은 사업이 일어납니다. 도시에는 여러 개의 게이트 (IP 주소)가 있습니다. 각 게이트에는 이름 ( "North Gate", "River Gate", "Southampton Gate"...)이 있지만 게이트 이름은 도시 이름이 아닙니다. 또한 게이트 이름을 사용하여 도시 이름을 추론 할 수 없습니다. "North Gate"는 한 도시가 아니라 큰 도시의 절반을 차지합니다. 그러나 낯선 사람 (IP 패킷)이 강을 따라 걸어 가서 현지인에게 다음과 같이 묻습니다. 현지인은 "물론 올바른 길을 가고 있습니다. 30 분 안에 목적지에 도착할 것입니다."라고 말합니다.
이것은 내가 생각하는 것을 거의 보여줍니다.
좋은 소식은 : 실제 호스트 이름은 일반적으로 필요하지 않습니다. 대부분의 경우이 호스트의 IP 주소로 확인되는 모든 이름이 사용됩니다. (이방인은 노스 게이트를 통해 도시로 들어올 수 있지만 도움이되는 지역 주민들은 "왼쪽 2 번째"부분을 번역합니다.)
나머지 코너 의 경우이 구성 설정 의 최종 소스 (C 기능)를 사용해야합니다 gethostname(2)
. 이 기능은 또한 프로그램에 의해 호출됩니다 hostname
.
InetAddress.getLocalHost().getHostName()
더 휴대하기 쉬운 방법입니다.
exec("hostname")
실제로 운영 체제를 호출하여 hostname
명령 을 실행합니다 .
SO에 대한 몇 가지 다른 답변이 있습니다.
편집 : 당신은 AH의 대답을 봐야합니다 상황에 따라 또는 Arnout Engelen의 답변 을 예상대로 작동하지 않는 이유에 대한 자세한 내용을 살펴보십시오. 특별히 휴대용을 요청한이 사람에 대한 답변으로, 나는 여전히 getHostName()
괜찮다고 생각 하지만 고려해야 할 몇 가지 좋은 점을 제시합니다.
InetAddress.getLocalHost()
경우에 따라 루프백 장치를 반환합니다. 이 경우 getHostName()
"localhost"를 반환하는데, 그다지 유용하지는 않습니다.
다른 사람들이 지적했듯이 DNS 확인을 기반으로 호스트 이름을 얻는 것은 신뢰할 수 없습니다.
이 질문은 불행히도 2018 년 에도 여전히 관련이 있기 때문에 다른 시스템에서 일부 테스트를 실행하여 네트워크 독립적 인 솔루션을 공유하고 싶습니다.
다음 코드는 다음을 수행하려고 시도합니다.
Windows에서
를 COMPUTERNAME
통해 환경 변수를 읽습니다 System.getenv()
.
hostname.exe
응답을 실행 하고 읽습니다.
리눅스에서
를 HOSTNAME
통해 환경 변수를 읽으십시오System.getenv()
hostname
응답을 실행 하고 읽습니다.
읽기 /etc/hostname
(이 cat
코드는 이미 실행하고 읽을 코드가 포함되어 있기 때문에 실행 중입니다. 파일을 읽는 것이 더 좋을 것입니다).
코드:
public static void main(String[] args) throws IOException {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
System.out.println("Windows computer name through env:\"" + System.getenv("COMPUTERNAME") + "\"");
System.out.println("Windows computer name through exec:\"" + execReadToString("hostname") + "\"");
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac os x")) {
System.out.println("Unix-like computer name through env:\"" + System.getenv("HOSTNAME") + "\"");
System.out.println("Unix-like computer name through exec:\"" + execReadToString("hostname") + "\"");
System.out.println("Unix-like computer name through /etc/hostname:\"" + execReadToString("cat /etc/hostname") + "\"");
}
}
public static String execReadToString(String execCommand) throws IOException {
try (Scanner s = new Scanner(Runtime.getRuntime().exec(execCommand).getInputStream()).useDelimiter("\\A")) {
return s.hasNext() ? s.next() : "";
}
}
다른 운영 체제에 대한 결과 :
macOS 10.13.2
Unix-like computer name through env:"null"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""
오픈 수세 13.1
Unix-like computer name through env:"machinename"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""
우분투 14.04 LTS
이것은 echo $HOSTNAME
올바른 호스트 이름을 반환하기 때문에 다소 이상 하지만 다음과 같은 System.getenv("HOSTNAME")
것은 아닙니다.
Unix-like computer name through env:"null"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:"machinename
"
편집 : legolas108 에 따르면 Java 코드 System.getenv("HOSTNAME")
를 실행 export HOSTNAME
하기 전에 실행 하면 Ubuntu 14.04 에서 작동 합니다.
윈도우 7
Windows computer name through env:"MACHINENAME"
Windows computer name through exec:"machinename
"
윈도우 10
Windows computer name through env:"MACHINENAME"
Windows computer name through exec:"machinename
"
기계 이름이 바뀌었지만 대문자와 구조를 유지했습니다. 를 실행할 때 추가 줄 바꿈을 참고하십시오 hostname
.
export HOSTNAME
이전에 우분투 14.04 LTS에서 Java 코드를 실행 그것은 또한에 의해 반환됩니다 System.getenv("HOSTNAME")
.
export HOSTNAME
Java를 사용 하려면 명시 적 으로 사용해야합니까? PATH와 같은 기본 env var 여야한다고 생각했습니다.
\A
구분 기호 는를 사용하여 전체 InputStream을 읽는 해킹 일뿐 Scanner
입니다.
InetAddress.getLocalHost().getHostName()
(닉이 설명한대로) 더 좋지만 여전히 그리 좋지는 않습니다.
하나의 호스트는 여러 다른 호스트 이름으로 알려질 수 있습니다. 일반적으로 호스트는 특정 컨텍스트에서 호스트 이름을 찾습니다.
예를 들어, 웹 애플리케이션에서 현재 처리중인 요청을 발행 한 사람이 사용한 호스트 이름을 찾고있을 수 있습니다. 가장 적합한 방법은 웹 응용 프로그램에 사용중인 프레임 워크에 따라 다릅니다.
다른 종류의 인터넷 연결 서비스에서는 '외부'에서 서비스를 사용할 수있는 호스트 이름이 필요합니다. 프록시, 방화벽 등으로 인해 이것은 서비스가 설치된 시스템의 호스트 이름이 아닐 수도 있습니다. 합리적인 기본값을 설정하려고 시도 할 수 있지만이를 설치하는 사람은 반드시 구성 할 수 있어야합니다.
이 주제에 대해 이미 답변을 받았지만 더 많은 할 말이 있습니다.
우선 : 분명히 여기에 몇 가지 정의가 필요합니다. 는 InetAddress.getLocalHost().getHostName()
당신에게 호스트의 이름을 제공 네트워크 관점에서 본 . 이 접근 방식의 문제점은 다른 답변에 잘 설명되어 있습니다. 종종 DNS 조회가 필요합니다. 호스트에 여러 개의 네트워크 인터페이스가 있고 때로는 실패 할 경우 모호합니다 (아래 참조).
그러나 모든 OS에는 다른 이름도 있습니다. 네트워크가 초기화되기 훨씬 전에 부트 프로세스 초기에 정의되는 호스트 이름. Windows는이를 컴퓨터 이름 으로 지칭하고 , Linux는이를 커널 호스트 이름이라고 하며 Solaris는 단어 nodename을 사용합니다 . 나는 computername 이라는 단어를 가장 좋아 하므로 앞으로 그 단어를 사용할 것입니다.
리눅스 / 유닉스 컴퓨터 이름을 사용하면 C 함수에서 무엇을 얻을 gethostname()
, 또는 hostname
쉘 또는에서 명령 HOSTNAME
쉘 강타 - 같은 환경 변수.
Windows에서 컴퓨터 이름은 환경 변수 COMPUTERNAME
또는 Win32 GetComputerName
기능 에서 얻는 것입니다 .
Java는 'computername'으로 정의한 것을 얻을 수있는 방법이 없습니다. 물론, Windows calling와 같은 다른 답변에 설명 된 해결 방법이 System.getenv("COMPUTERNAME")
있지만 Unix / Linux에서는 JNI / JNA 또는에 의지하지 않으면 좋은 해결 방법이 없습니다 Runtime.exec()
. JNI / JNA 솔루션이 마음에 들지 않으면 gethostname4j 가 있으며 간단하고 사용하기 쉽습니다.
표준 Java 메소드를 사용하여 컴퓨터 이름을 얻을 수없는 상황에 쉽게 도달 할 수있는 방법을 보여주는 Linux 및 Solaris의 두 가지 예를 살펴 보겠습니다.
설치 중 호스트 이름이 'chicago'인 새로 작성된 시스템에서 이제 커널 호스트 이름을 변경합니다.
$ hostnamectl --static set-hostname dallas
이제 호스트 이름 명령에서 알 수 있듯이 커널 호스트 이름은 'dallas'입니다.
$ hostname
dallas
그러나 우리는 여전히
$ cat /etc/hosts
127.0.0.1 localhost
127.0.0.1 chicago
이 구성에는 잘못된 구성이 없습니다. 호스트의 네트워크 이름 (또는 루프백 인터페이스의 이름)이 호스트의 컴퓨터 이름과 다르다는 것을 의미합니다.
이제 실행을 시도 InetAddress.getLocalHost().getHostName()
하면 java.net.UnknownHostException이 발생합니다. 당신은 기본적으로 붙어 있습니다. 'dallas'또는 'chicago'값을 검색 할 방법이 없습니다.
아래 예는 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
리눅스 예제에서와 마찬가지로 호출 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 보고서가 표시됩니다 ( link1 , link2) . 그러나 해당 보고서에 대한 의견을 바탕으로 JDK 팀은이 문제를 크게 오해 한 것으로 보이므로 해결되지 않을 것입니다.
RFE에서 다른 프로그래밍 언어와 비교하는 것이 좋습니다.
환경 변수는 COMPUTERNAME
Windows, HOSTNAME
대부분의 최신 Unix / Linux 쉘 에서 유용한 수단을 제공 할 수도 있습니다 .
참조 : https://stackoverflow.com/a/17956000/768795
InetAddress.getLocalHost().getHostName()
여러 사람들이 지적했듯이 모든 환경에서 해당 기능이 작동하지 않기 때문에 이를 "보완"방법으로 사용 하고 있습니다.
Runtime.getRuntime().exec("hostname")
또 다른 가능한 보충제입니다. 이 단계에서는 사용하지 않았습니다.
import java.net.InetAddress;
import java.net.UnknownHostException;
// try InetAddress.LocalHost first;
// NOTE -- InetAddress.getLocalHost().getHostName() will not work in certain environments.
try {
String result = InetAddress.getLocalHost().getHostName();
if (StringUtils.isNotEmpty( result))
return result;
} catch (UnknownHostException e) {
// failed; try alternate means.
}
// try environment properties.
//
String host = System.getenv("COMPUTERNAME");
if (host != null)
return host;
host = System.getenv("HOSTNAME");
if (host != null)
return host;
// undetermined.
return null;
StringUtils
Apache 혼동 -lang 프로젝트에서 제공하는 혼란 스럽습니다 . 그것을 사용하는 것이 좋습니다.
System.getenv("HOSTNAME")
Java에서 Beanshell을 통해 Mac에서 어떻게 든 null이 나왔지만 정상적으로 PATH
추출되었습니다. echo $HOSTNAME
Mac 에서도 할 수 있습니다 .System.getenv ( "HOSTNAME") 만 문제가있는 것 같습니다. 이상한.
Java로 현재 컴퓨터의 호스트 이름을 얻는 가장 쉬운 방법은 다음과 같습니다.
import java.net.InetAddress;
import java.net.UnknownHostException;
public class getHostName {
public static void main(String[] args) throws UnknownHostException {
InetAddress iAddress = InetAddress.getLocalHost();
String hostName = iAddress.getHostName();
//To get the Canonical host name
String canonicalHostName = iAddress.getCanonicalHostName();
System.out.println("HostName:" + hostName);
System.out.println("Canonical Host Name:" + canonicalHostName);
}
}
maven central의 외부 종속성을 사용하지 않으려면 gethostname4j를 작성 하여이 문제를 직접 해결하십시오. JNA를 사용하여 libc의 gethostname 함수를 호출하거나 Windows에서 ComputerName을 가져 와서 문자열로 반환합니다.
hostName == null;
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
{
while (interfaces.hasMoreElements()) {
NetworkInterface nic = interfaces.nextElement();
Enumeration<InetAddress> addresses = nic.getInetAddresses();
while (hostName == null && addresses.hasMoreElements()) {
InetAddress address = addresses.nextElement();
if (!address.isLoopbackAddress()) {
hostName = address.getHostName();
}
}
}
}
한 줄짜리 ... 크로스 플랫폼 (Windows-Linux-Unix-Mac (Unix)) [항상 작동, DNS 필요 없음] :
String hostname = new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))
.readLine();
끝났어 !!
InetAddress.getLocalHost (). getHostName ()은 개발자 수준에서 최고의 추상화이므로 둘 중 가장 좋은 방법입니다.