おはようございます。
JavaのInetAddress#getHostName()って使ってますか?
以前何も気にせずこのメソッドを使った際、Linuxのhostnameコマンドと結果が異なったことがあり、そのとき調査したことをまとめます。
環境
クラウドサービス:Google Compute Engine
OS:CentOS8
Java:OpenJDK11
Javaセットアップ
sudo yum install -y java-11-openjdk
sudo yum install -y java-11-openjdk-devel
ひとまず確認しておくべきファイル
1. /etc/hostname
(CentOS6までは/etc/sysconfig/network)
[zakisanbaiman@test01 ~]$ cat /etc/hostname
test01
2. /etc/hosts
これはよく触る機会が多いと思います
[zakisanbaiman@test01 ~]$ cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.146.0.4 test02
169.254.169.254 metadata.google.internal # Added by Google
場合によってはこれ以外のファイルを参照することもあるみたいですが、基本的にはこの2つを確認すれば良いです。
各コマンドの参照先
それでは、各コマンドがどこを参照しているか確認します。
hostnameコマンド
[zakisanbaiman@test01 dev]$ hostname
test01
hostnameコマンドは/etc/hostnameを参照します。
ただし「hostname [ホスト名]」でホスト名を一時的に変更した際はそちらを優先的に表示するようです。
/etc/hostnameとhostnameコマンドで差異が発生する場合はhostnamectl statusでTransient hostname(一時的なホスト名)が設定されていないか確認すると良いでしょう。
Java: InetAddress#getHostName()
こちらも基本的にはhostnameコマンドと同じ/etc/hostnameと同じものを表示します。
ただし、InetAddressのインスタンスがホスト名を指定して構築されていた場合はそちらを優先します。
hostnameコマンドと合わせたいならこっちを使うべきでしょう。
ただしインスタンスの作り方によっては、ローカルループバックアドレスを取得したりとロジックが異なるので注意。
Java: Java:InetAddress#getCanonicalHostName()
こちらはマシンに設定されているネームサービスを使ってホスト名を取得するようです。
今回試した環境(CentOS8)では/etc/hostsを使った逆名前解決が行われていました。
※逆名前解決はIPアドレスをキーにしてホスト名を取得する方法です。
ちなみに1つのIPに複数ホスト名が記載されている場合は一番左のホスト名を表示します。
一覧にすると
|コマンド|参照先|実際の表示|
|:-----------------|:------------------|:------------------|
|hostname|/etc/hostname|test01|
|Java: InetAddress#getHostName()|/etc/hostname|test01|
|Java: InetAddress#getCanonicalHostName()|/etc/hosts|test02|
まとめ
hostnameと合わせたいならgetHostName()を使えばいい、という簡単な話ではなくhostnameで取得したものをJavaアプリケーション内で読み込むなどした方が間違いがなさそうです。
ホスト名を取得するだけでもいろんなやり方があり、一歩間違えると致命的な事故になりかねないので気を付けたいです。
追記(ちょっと大事)
ずっとhostnameを使ってきましたが、Linuxコマンドでホスト名を取得したい場合はuname -nを使う方が書き換えのリスクがなく安心です。
参考
ここまで読んでいただきありがとうございました。