web-dev-qa-db-ja.com

JavaのDNSで解決できない場合、ローカルホスト名を取得するにはどうすればよいですか?

これは以前に尋ねられるべきもののように聞こえます、そしてそれはある種のものです、しかし私はそれがDNS(Javaで)を通して解決できないときでさえマシンのローカルホスト名とIPアドレスを取得しようとしています。

NetworkInterfaces.getNetworkInterfaces()を繰り返すことで、解決せずにローカルIPアドレスを取得できます。

私が見つけたこの質問への回答は、getLocalHost()を使用することを示しています

InetAddress localhost = Java.net.InetAddress.getLocalHost();
hostName = localhost.getHostName();

ただし、ホスト名がDNSを介して解決できない場合、これはUnknownHostExceptionをスローします。

舞台裏でDNSルックアップを行わずにローカルホスト名を取得する方法はありませんか?

編集:取得されたIPアドレスは10.4.168.23です。例外はJava.net.UnknownHostException: cms1.companyname.com: cms1.companyname.com(疑似匿名性のためにホスト名が変更されました)であり、hostsファイルにホスト名が含まれていません。ただし、ホスト名はknowであるため、例外がスローされない限り取得できない理由がわかりません。

15
Shawn D.

はい、ありますshould Javaで、ネームサービスルックアップに頼らずにホスト名を取得する方法がありますが、残念ながらありません。

ただし、次のようなことができます。

if (System.getProperty("os.name").startsWith("Windows")) {
    // Windows will always set the 'COMPUTERNAME' variable
    return System.getenv("COMPUTERNAME");
} else {
    // If it is not Windows then it is most likely a Unix-like operating system
    // such as Solaris, AIX, HP-UX, Linux or MacOS.

    // Most modern shells (such as Bash or derivatives) sets the 
    // HOSTNAME variable so lets try that first.
    String hostname = System.getenv("HOSTNAME");
    if (hostname != null) {
       return hostname;
    } else {

       // If the above returns null *and* the OS is Unix-like
       // then you can try an exec() and read the output from the 
       // 'hostname' command which exist on all types of Unix/Linux.

       // If you are an OS other than Unix/Linux then you would have 
       // to do something else. For example on OpenVMS you would find 
       // it like this from the Shell:  F$GETSYI("NODENAME") 
       // which you would probably also have to find from within Java 
       // via an exec() call.

       // If you are on zOS then who knows ??

       // etc, etc
    }
}

これにより、従来のSun JDKプラットフォーム(Windows、Solaris、Linux)で必要なものが100%得られますが、OSがよりエキゾチックである場合(Javaの観点から))は簡単ではなくなります。を参照してください。コード例のコメント。

もっと良い方法があったらいいのにと思います。

12
peterh

この質問は古いものですが、Javaでマシンのホスト名を取得することはまだ簡単ではないため、残念ながら依然として関連性があります。さまざまなシステムでいくつかのテストを実行した私のソリューションは次のとおりです。

_public static void main(String[] args) throws IOException {
        String OS = System.getProperty("os.name").toLowerCase();

        if (OS.indexOf("win") >= 0) {
            System.out.println("Windows computer name throguh env:\"" + System.getenv("COMPUTERNAME") + "\"");
            System.out.println("Windows computer name through exec:\"" + execReadToString("hostname") + "\"");
        } else {
            if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0) {
                System.out.println("Linux computer name throguh env:\"" + System.getenv("HOSTNAME") + "\"");
                System.out.println("Linux computer name through exec:\"" + execReadToString("hostname") + "\"");
                System.out.println("Linux computer name through /etc/hostname:\"" + execReadToString("cat /etc/hostname") + "\"");
            }
        }
    }

    public static String execReadToString(String execCommand) throws IOException {
        Process proc = Runtime.getRuntime().exec(execCommand);
        try (InputStream stream = proc.getInputStream()) {
            try (Scanner s = new Scanner(stream).useDelimiter("\\A")) {
                return s.hasNext() ? s.next() : "";
            }
        }
    }
_

さまざまなオペレーティングシステムの結果:

OpenSuse 13.1

_Linux computer name throguh env:"machinename"
Linux computer name through exec:"machinename
"
Linux computer name through /etc/hostname:""
_

buntu 14.04 LTS _echo $HOSTNAME_は正しいホスト名を返すので、これはちょっと奇妙ですが、System.getenv("HOSTNAME")は返しません(ただし、これは私の環境でのみ問題になる可能性があります):

_Linux computer name throguh env:"null"
Linux computer name through exec:"machinename
"
Linux computer name through /etc/hostname:"machinename
"
_

Windows 7

_Windows computer name throguh env:"MACHINENAME"
Windows computer name through exec:"machinename
"
_

マシン名は(一部の)匿名化のために置き換えられましたが、大文字と構造は維持しています。 hostnameを実行するときは余分な改行に注意してください。場合によっては、それを考慮に入れる必要があります。

6
Malt

または、 [〜#〜] jna [〜#〜] を使用してUNIXでgethostname関数を呼び出し、DNSの逆引き参照を回避します。

注:Linuxでは、gethostnameは単にunameを呼び出し、出力を解析すると思います。 OS Xでは、ホスト名がDNSの影響を受ける可能性があるため、状況はより複雑ですが、これらの副作用は別として、それは間違いなくhostnameから得られるものです。

_import com.Sun.jna.LastErrorException
import com.Sun.jna.Library
import com.Sun.jna.Native

...

private static final C c = (C) Native.loadLibrary("c", C.class);

private static interface C extends Library {
    public int gethostname(byte[] name, int size_t) throws LastErrorException;
}

public String getHostName() {
    byte[] hostname = new byte[256];
    c.gethostname(hostname, hostname.length)
    return Native.toString(hostname)
}
_

_jna-platform.jar_にはWin32関数が含まれているため、Kernel32Util.getComputerName()を呼び出すのと同じくらい簡単です。

2
Danny Thomas

IPアドレスとして127.0.0.1を取得している場合は、オペレーティングシステム固有のhostsファイルを見つけて、その中のホスト名にマッピングを追加する必要がある場合があります。

1
sinha

これはちょっとしたハックです。ただし、Javaから新しいプロセスを起動し、hostnameコマンドを実行することもできます。子プロセスの出力ストリームを読み取ると、ローカルホストの名前がわかります。

1
Vineet Reynolds

DNSが構成されていない場合、Javaは/ etc/hostsファイルを読み取ります。または、対応するC関数が読み取ります。

1
user207421

linuxで読む

/proc/sys/kernel/hostname
0
weberjn

Maven Centralからの外部依存関係を使用することに反対しない場合は、この問題を自分で解決するためにgethostname4jを作成しました。 JNAを使用してlibcのgethostname関数を呼び出し(またはWindowsではComputerNameを取得し)、それを文字列として返します。

https://github.com/mattsheppard/gethostname4j

(これは@ danny-thomasが提案したものとほぼ同じだと思いますが、すでにMavenを使用している場合はおそらくもっと便利です;)

0
Matt Sheppard