回答:
厳密に言うと- hostname(1)
または-Unixで呼び出す以外に選択肢はありませんgethostname(2)
。これはお使いのコンピュータの名前です。このようなIPアドレスでホスト名を特定しようとする試み
InetAddress.getLocalHost().getHostName()
いくつかの状況では失敗するはずです:
また、IPアドレスの名前とホストの名前(ホスト名)を混同しないでください。比喩はそれをより明確にするかもしれません:
「ロンドン」と呼ばれる大都市(サーバー)があります。市壁の内側で多くのビジネスが起こります。市にはいくつかのゲート(IPアドレス)があります。各ゲートには名前があります(「ノースゲート」、「リバーゲート」、「サウサンプトンゲート」...)。ただし、ゲートの名前は都市の名前ではありません。また、ゲートの名前を使用して都市の名前を推測することはできません。「North Gate」は、1つの都市だけでなく、大都市の半分をキャッチします。しかし、見知らぬ人(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
応答を実行して読み取る
Linuxの場合
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:""
OpenSuse 13.1
Unix-like computer name through env:"machinename"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""
Ubuntu 14.04 LTSecho $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 で動作します。
Windows 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
Ubuntu 14.04 LTSでJavaコードを実行する前であれば、それもによって返されSystem.getenv("HOSTNAME")
ます。
export HOSTNAME
Javaで明示的に使用する必要がありますか?私はそれがPATHのようなデフォルトのenv varであるべきだと思いました。
\A
区切り文字は、を使用してInputStream全体を読み取るためのハックにすぎませんScanner
。
InetAddress.getLocalHost().getHostName()
(ニックによって説明されているように)優れていますが、それでもあまり良くありません
1つのホストは、さまざまなホスト名で認識されます。通常、特定のコンテキストでホストが持っているホスト名を探します。
たとえば、Webアプリケーションでは、現在処理しているリクエストを発行した人が使用しているホスト名を探している可能性があります。最適な方法を見つけるには、Webアプリケーションに使用しているフレームワークに依存します。
他のある種のインターネット向けサービスでは、「外部」からサービスが利用できるホスト名が必要になります。プロキシ、ファイアウォールなどにより、これはサービスがインストールされているマシンのホスト名ではない可能性があります。妥当なデフォルトを考え出そうとするかもしれませんが、これをインストールする人は誰でもこれを構成可能にする必要があります。
このトピックについてはすでに回答済みですが、他にも言うべきことがあります。
まず第一に、明らかにここでいくつかの定義が必要です。には、ネットワークの観点から見InetAddress.getLocalHost().getHostName()
たホストの名前が表示されます。このアプローチの問題は他の回答に詳しく記載されています。DNSルックアップが必要な場合が多く、ホストに複数のネットワークインターフェースがあり、単純に失敗する場合があります(以下を参照)。
しかし、どのOSにも別の名前があります。ブートプロセスの非常に早い段階で、ネットワークが初期化されるずっと前に定義されるホストの名前。Windowsではこれをcomputernameと呼び、Linuxではこれをカーネルホスト名と呼び、Solarisではnodenameという単語を使用します。Computernameという言葉が一番好きなので、これからこの言葉を使用します。
Linux / Unixでは、computernameはC関数から取得したものgethostname()
、またはBashのようなhostname
シェルのシェルまたはHOSTNAME
環境変数からのコマンドです。
Windowsでは、コンピューター名は環境変数COMPUTERNAME
またはWin32 GetComputerName
関数から取得したものです。
Javaには、「computername」として定義したものを取得する方法がありません。もちろん、Windowsの呼び出しのような他の回答に記載されている回避策はありますSystem.getenv("COMPUTERNAME")
が、Unix / Linuxでは、JNI / JNAまたはに頼らずに適切な回避策はありませんRuntime.exec()
。JNI / JNAソリューションを気にしない場合は、非常にシンプルで非常に使いやすいgethostname4jがあります。
1つはLinuxから、もう1つはSolarisから2つの例を見ていきましょう。これらは、標準のJavaメソッドを使用してコンピューター名を取得できない状況に簡単に入る方法を示しています。
新しく作成されたシステムで、インストール中のホストの名前が「chicago」である場合、いわゆるカーネルホスト名を変更します。
$ hostnamectl --static set-hostname 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に基づいています。
ホストは、ループバック名<>ノード名になるように意図的に構成されています。
つまり、次のようになります。
$ 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レポート明らかにするリンク1、リンク2を。ただし、そのレポートのコメントから判断すると、この問題は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 commons-langプロジェクトによって提供されます。それ、またはそれに似たものを使用することを強くお勧めします。
System.getenv("HOSTNAME")
、JavaのBeanshellを介してMacでnullになりましたPATH
が、正常に抽出されました。また、私は何ができるecho $HOSTNAME
だけでSystem.getenv(「HOSTNAME」)は、問題を持っているように見える、あまりにもMac上で。奇妙な。
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();
}
}
}
}
ただ1つのライナー...クロスプラットフォーム(Windows-Linux-Unix-Mac(Unix))[常に機能し、DNSは不要]:
String hostname = new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))
.readLine();
完了です!
InetAddress.getLocalHost()。getHostName()は、開発者レベルでの最適な抽象化であるため、2つの方法のうち最良の方法です。