Welche der folgenden Methoden ist die beste und portabelste Methode, um den Hostnamen des aktuellen Computers in Java abzurufen?
Runtime.getRuntime().exec("hostname")
vs.
InetAddress.getLocalHost().getHostName()
Welche der folgenden Methoden ist die beste und portabelste Methode, um den Hostnamen des aktuellen Computers in Java abzurufen?
Runtime.getRuntime().exec("hostname")
vs.
InetAddress.getLocalHost().getHostName()
Antworten:
Genau genommen haben Sie keine andere Wahl, als entweder
hostname(1)
oder unter Unix anzurufengethostname(2)
. Dies ist der Name Ihres Computers. Jeder Versuch, den Hostnamen anhand einer solchen IP-Adresse zu ermittelnist unter bestimmten Umständen zum Scheitern verurteilt:
Verwechseln Sie auch nicht den Namen einer IP-Adresse mit dem Namen des Hosts (Hostname). Eine Metapher könnte es klarer machen:
Das zeigt es ziemlich genau, denke ich.
Die gute Nachricht ist: Der echte Hostname ist normalerweise nicht erforderlich. In den meisten Fällen reicht jeder Name aus, der in eine IP-Adresse auf diesem Host aufgelöst wird. (Der Fremde könnte die Stadt über Northgate betreten, aber hilfreiche Einheimische übersetzen den Teil "2. links".)
In den verbleibenden Eckfällen müssen Sie die endgültige Quelle dieser Konfigurationseinstellung verwenden - dies ist die C-Funktion
gethostname(2)
. Diese Funktion wird auch vom Programm aufgerufenhostname
.quelle
InetAddress.getLocalHost().getHostName()
ist der tragbarere Weg.exec("hostname")
ruft tatsächlich das Betriebssystem auf, um denhostname
Befehl auszuführen .Hier sind einige andere verwandte Antworten auf SO:
BEARBEITEN: Sie sollten sich die Antwort von AH oder Arnout Engelen ansehen , um zu erfahren, warum dies je nach Ihrer Situation möglicherweise nicht wie erwartet funktioniert. Als Antwort für diese Person, die speziell tragbare Geräte angefordert hat, denke ich immer noch, dass dies
getHostName()
in Ordnung ist, aber sie bringt einige gute Punkte vor, die berücksichtigt werden sollten.quelle
InetAddress.getLocalHost()
in einigen Fällen gibt den Loopback - Device. In diesem Fall wirdgetHostName()
"localhost" zurückgegeben, was nicht sehr nützlich ist.Wie andere angemerkt haben, ist es unzuverlässig, den Hostnamen basierend auf der DNS-Auflösung zu erhalten.
Da diese Frage 2018 leider immer noch relevant ist , möchte ich Ihnen meine netzwerkunabhängige Lösung mit einigen Testläufen auf verschiedenen Systemen vorstellen.
Der folgende Code versucht Folgendes zu tun:
Unter Windows
Lesen Sie die
COMPUTERNAME
Umgebungsvariable durchSystem.getenv()
.Führen
hostname.exe
Sie die Antwort aus und lesen Sie sieUnter Linux
Lesen Sie die
HOSTNAME
Umgebungsvariable durchSystem.getenv()
Führen
hostname
Sie die Antwort aus und lesen Sie sieLesen
/etc/hostname
(dazu führe ich aus,cat
da das Snippet bereits Code zum Ausführen und Lesen enthält. Es wäre jedoch besser, die Datei einfach zu lesen).Der Code:
Ergebnisse für verschiedene Betriebssysteme:
macOS 10.13.2
OpenSuse 13.1
Ubuntu 14.04 LTS Dieser ist etwas seltsam, da er
echo $HOSTNAME
den richtigen Hostnamen zurückgibt, aberSystem.getenv("HOSTNAME")
nicht:EDIT: Nach legolas108 ,
System.getenv("HOSTNAME")
arbeitet auf Ubuntu 14.04 , wenn Sie ausführen ,export HOSTNAME
bevor Sie den Java - Code ausgeführt wird .Windows 7
Windows 10
Die Maschinennamen wurden ersetzt, aber ich habe die Groß- und Kleinschreibung und Struktur beibehalten. Beachten Sie den zusätzlichen Zeilenumbruch bei der Ausführung.
hostname
In einigen Fällen müssen Sie ihn möglicherweise berücksichtigen.quelle
export HOSTNAME
den Java-Code vor dem Ausführen unter Ubuntu 14.04 LTS ausführen, wird er auch von zurückgegebenSystem.getenv("HOSTNAME")
.export HOSTNAME
für Java verwenden, um es zu verwenden? Ich dachte, es sollte eine Standard-Umgebung wie PATH sein.\A
Trennzeichen ist nur ein Hack zum Lesen des gesamten InputStream mit aScanner
.InetAddress.getLocalHost().getHostName()
ist besser (wie von Nick erklärt), aber immer noch nicht sehr gutEin Host kann unter vielen verschiedenen Hostnamen bekannt sein. Normalerweise suchen Sie nach dem Hostnamen, den Ihr Host in einem bestimmten Kontext hat.
In einer Webanwendung suchen Sie möglicherweise nach dem Hostnamen, der von demjenigen verwendet wird, der die Anforderung ausgegeben hat, die Sie gerade bearbeiten. Wie Sie dieses am besten finden, hängt davon ab, welches Framework Sie für Ihre Webanwendung verwenden.
Bei einer anderen Internetverbindung möchten Sie, dass der Hostname, über den Ihr Dienst verfügbar ist, von außen verfügbar ist. Aufgrund von Proxys, Firewalls usw. ist dies möglicherweise nicht einmal ein Hostname auf dem Computer, auf dem Ihr Dienst installiert ist. Sie könnten versuchen, einen vernünftigen Standard festzulegen, aber Sie sollten diesen auf jeden Fall für jeden konfigurierbar machen, der diesen installiert.
quelle
Obwohl dieses Thema bereits beantwortet wurde, gibt es noch mehr zu sagen.
Zuallererst: Natürlich brauchen wir hier einige Definitionen. Das
InetAddress.getLocalHost().getHostName()
gibt Ihnen den Namen des Hosts aus der Netzwerkperspektive . Die Probleme mit diesem Ansatz sind in den anderen Antworten gut dokumentiert: Oft ist eine DNS-Suche erforderlich, es ist nicht eindeutig, ob der Host über mehrere Netzwerkschnittstellen verfügt, und manchmal schlägt dies einfach fehl (siehe unten).Aber auf jedem Betriebssystem gibt es auch einen anderen Namen. Ein Name des Hosts, der sehr früh im Startvorgang definiert wird, lange bevor das Netzwerk initialisiert wird. Windows bezeichnet dies als Computernamen , Linux nennt es Kernel-Hostname und Solaris verwendet das Wort Knotenname . Das Wort Computername gefällt mir am besten , daher werde ich dieses Wort von nun an verwenden.
Den Computernamen finden
Unter Linux / Unix erhalten Sie den Computernamen von der C-Funktion
gethostname()
oder denhostname
Befehl von der Shell oder derHOSTNAME
Umgebungsvariablen in Bash-ähnlichen Shells.Unter Windows erhalten Sie den Computernamen von der Umgebungsvariablen
COMPUTERNAME
oder der Win32-GetComputerName
Funktion.Java hat keine Möglichkeit, das zu erhalten, was ich als "Computername" definiert habe. Sicher, es gibt Problemumgehungen, wie in anderen Antworten beschrieben, wie zum Beispiel für Windows-Aufrufe
System.getenv("COMPUTERNAME")
, aber unter Unix / Linux gibt es keine gute Problemumgehung, ohne auf JNI / JNA oder zurückzugreifenRuntime.exec()
. Wenn Ihnen eine JNI / JNA-Lösung nichts ausmacht, gibt es gethostname4j, das kinderleicht und sehr einfach zu bedienen ist.Fahren wir mit zwei Beispielen fort, einem von Linux und einem von Solaris, die zeigen, wie Sie leicht in eine Situation geraten können, in der Sie den Computernamen nicht mit Standard-Java-Methoden erhalten können.
Linux Beispiel
Auf einem neu erstellten System, auf dem der Host während der Installation als "Chicago" bezeichnet wurde, ändern wir jetzt den sogenannten Kernel-Hostnamen:
Jetzt lautet der Kernel-Hostname 'dallas', wie aus dem Befehl hostname hervorgeht:
Aber wir haben immer noch
Darin liegt keine Fehlkonfiguration. Dies bedeutet lediglich, dass sich der Netzwerkname des Hosts (oder vielmehr der Name der Loopback-Schnittstelle) vom Computernamen des Hosts unterscheidet.
Versuchen Sie nun die Ausführung
InetAddress.getLocalHost().getHostName()
und es wird eine java.net.UnknownHostException ausgelöst. Sie stecken im Grunde fest. Es gibt keine Möglichkeit, weder den Wert 'dallas' noch den Wert 'chicago' abzurufen.Solaris Beispiel
Das folgende Beispiel basiert auf Solaris 11.3.
Der Host wurde absichtlich so konfiguriert, dass der Loopback-Name <> Knotenname ist.
Mit anderen Worten haben wir:
und den Inhalt von / etc / hosts:
und das Ergebnis des Befehls hostname wäre:
Genau wie im Linux-Beispiel schlägt ein Aufruf von
InetAddress.getLocalHost().getHostName()
fehlGenau wie im Linux-Beispiel stecken Sie jetzt fest. Es gibt keine Möglichkeit, weder den Wert 'dallas' noch den Wert 'chicago' abzurufen.
Wann wirst du wirklich damit kämpfen?
Sehr oft werden Sie feststellen, dass
InetAddress.getLocalHost().getHostName()
tatsächlich ein Wert zurückgegeben wird, der dem Computernamen entspricht. Es gibt also kein Problem (außer dem zusätzlichen Aufwand für die Namensauflösung).Das Problem tritt normalerweise in PaaS-Umgebungen auf, in denen ein Unterschied zwischen dem Computernamen und dem Namen der Loopback-Schnittstelle besteht. Zum Beispiel melden Leute Probleme in Amazon EC2.
Fehler- / RFE-Berichte
Ein bisschen Suchen zeigt diesen RFE-Bericht: Link1 , Link2 . Nach den Kommentaren zu diesem Bericht zu urteilen, scheint das Problem jedoch vom JDK-Team weitgehend missverstanden worden zu sein, so dass es unwahrscheinlich ist, dass es behoben wird.
Ich mag den Vergleich in der RFE mit anderen Programmiersprachen.
quelle
Umgebungsvariablen können ebenfalls ein nützliches Mittel sein -
COMPUTERNAME
unter WindowsHOSTNAME
auf den meisten modernen Unix / Linux-Shells.Siehe: https://stackoverflow.com/a/17956000/768795
Ich verwende diese als "ergänzende" Methoden
InetAddress.getLocalHost().getHostName()
, da diese Funktion, wie mehrere Leute betonen, nicht in allen Umgebungen funktioniert.Runtime.getRuntime().exec("hostname")
ist eine weitere mögliche Ergänzung. Zu diesem Zeitpunkt habe ich es noch nicht benutzt.quelle
StringUtils
, wird es vom Apache commons-lang-Projekt bereitgestellt. Die Verwendung oder ähnliches wird dringend empfohlen.System.getenv("HOSTNAME")
kam auf dem Mac über Beanshell für Java null heraus, wurde aberPATH
ok extrahiert. Ich könnte es auchecho $HOSTNAME
auf einem Mac tun , nur System.getenv ("HOSTNAME") scheint ein Problem zu haben. Seltsam.Der portabelste Weg, um den Hostnamen des aktuellen Computers in Java abzurufen, ist wie folgt:
quelle
Wenn Sie nicht gegen die Verwendung einer externen Abhängigkeit von maven central sind, habe ich gethostname4j geschrieben, um dieses Problem für mich selbst zu lösen. Es verwendet nur JNA, um die Funktion gethostname von libc aufzurufen (oder den Computernamen unter Windows abzurufen) und gibt sie als Zeichenfolge an Sie zurück.
https://github.com/mattsheppard/gethostname4j
quelle
quelle
Nur einzeilig ... plattformübergreifend (Windows-Linux-Unix-Mac (Unix)) [Funktioniert immer, kein DNS erforderlich]:
Du bist fertig !!
quelle
InetAddress.getLocalHost (). GetHostName () ist der beste Ausweg, da dies die beste Abstraktion auf Entwicklerebene ist.
quelle