Manakah dari berikut ini adalah cara terbaik dan paling portabel untuk mendapatkan nama host dari komputer saat ini di Jawa?
Runtime.getRuntime().exec("hostname")
vs.
InetAddress.getLocalHost().getHostName()
Manakah dari berikut ini adalah cara terbaik dan paling portabel untuk mendapatkan nama host dari komputer saat ini di Jawa?
Runtime.getRuntime().exec("hostname")
vs.
InetAddress.getLocalHost().getHostName()
Jawaban:
Sebenarnya - Anda tidak punya pilihan selain memanggil salah satu
hostname(1)
atau - di Unixgethostname(2)
. Ini adalah nama komputer Anda. Upaya apa pun untuk menentukan nama host oleh alamat IP seperti inipasti gagal dalam beberapa keadaan:
Juga jangan bingung nama alamat IP dengan nama host (nama host). Metafora mungkin membuatnya lebih jelas:
Ini menggambarkannya menurut saya.
Kabar baiknya adalah: The nyata hostname ini biasanya tidak diperlukan. Dalam kebanyakan kasus, nama apa pun yang berubah menjadi alamat IP pada host ini akan dilakukan. (Orang asing itu mungkin memasuki kota oleh Northgate, tetapi penduduk setempat yang membantu menerjemahkan bagian "ke-2".)
Jika kasus sudut yang tersisa Anda harus menggunakan definitif sumber pengaturan konfigurasi ini - yang merupakan fungsi C
gethostname(2)
. Fungsi itu juga disebut oleh programhostname
.sumber
InetAddress.getLocalHost().getHostName()
adalah cara yang lebih portabel.exec("hostname")
sebenarnya memanggil sistem operasi untuk menjalankanhostname
perintah.Berikut adalah beberapa jawaban terkait lainnya pada SO:
EDIT: Anda harus melihat jawaban AH atau jawaban Arnout Engelen untuk perincian mengapa ini mungkin tidak berfungsi seperti yang diharapkan, tergantung pada situasi Anda. Sebagai jawaban untuk orang ini yang secara spesifik meminta portable, saya pikir masih
getHostName()
baik-baik saja, tetapi mereka memunculkan beberapa poin bagus yang harus dipertimbangkan.sumber
InetAddress.getLocalHost()
dalam beberapa kasus mengembalikan perangkat loopback. Dalam hal itu,getHostName()
mengembalikan "localhost", yang tidak terlalu berguna.Seperti yang telah dicatat orang lain, mendapatkan nama host berdasarkan resolusi DNS tidak dapat diandalkan.
Karena pertanyaan ini sayangnya masih relevan pada tahun 2018 , saya ingin berbagi dengan Anda solusi yang tidak tergantung jaringan saya, dengan beberapa pengujian berjalan pada sistem yang berbeda.
Kode berikut mencoba melakukan hal berikut:
Di Windows
Baca
COMPUTERNAME
variabel lingkungan melaluiSystem.getenv()
.Jalankan
hostname.exe
dan baca responsnyaDi Linux
Baca
HOSTNAME
variabel lingkungan melaluiSystem.getenv()
Jalankan
hostname
dan baca responsnyaBaca
/etc/hostname
(untuk melakukan ini saya mengeksekusicat
karena cuplikan sudah berisi kode untuk dieksekusi dan dibaca. Namun, membaca file akan lebih baik).Kode:
Hasil untuk sistem operasi yang berbeda:
macOS 10.13.2
OpenSuse 13.1
Ubuntu 14.04 LTS Yang ini agak aneh karena
echo $HOSTNAME
mengembalikan nama host yang benar, tetapiSystem.getenv("HOSTNAME")
tidak:EDIT: Menurut legolas108 ,
System.getenv("HOSTNAME")
berfungsi di Ubuntu 14.04 jika Anda menjalankanexport HOSTNAME
sebelum mengeksekusi kode Java.Windows 7
Windows 10
Nama-nama mesin telah diganti tetapi saya tetap menggunakan huruf besar dan struktur. Perhatikan baris baru tambahan saat menjalankan
hostname
, Anda mungkin harus mempertimbangkannya dalam beberapa kasus.sumber
export HOSTNAME
sebelum menjalankan kode Java pada Ubuntu 14.04 LTS juga dikembalikan olehSystem.getenv("HOSTNAME")
.export HOSTNAME
agar Java menggunakannya? Saya pikir itu harus menjadi standar env var seperti PATH.\A
pembatas hanyalah retasan untuk membaca seluruh InputStream menggunakan aScanner
.InetAddress.getLocalHost().getHostName()
lebih baik (seperti yang dijelaskan oleh Nick), tetapi masih belum terlalu bagusSatu host dapat dikenal dengan banyak nama host yang berbeda. Biasanya Anda akan mencari nama host yang dimiliki host Anda dalam konteks tertentu.
Misalnya, dalam aplikasi web, Anda mungkin mencari nama host yang digunakan oleh siapa pun yang mengeluarkan permintaan yang sedang Anda tangani. Cara terbaik menemukan itu tergantung pada kerangka mana yang Anda gunakan untuk aplikasi web Anda.
Dalam beberapa jenis layanan lain yang berhubungan dengan internet, Anda akan menginginkan nama host layanan Anda tersedia dari 'luar'. Karena proksi, firewall, dll. Ini bahkan mungkin bukan nama host di mesin tempat layanan Anda diinstal - Anda mungkin mencoba membuat default yang masuk akal, tetapi Anda harus membuat ini dapat dikonfigurasi untuk siapa pun yang menginstalnya.
sumber
Meskipun topik ini sudah dijawab, masih ada lagi yang bisa dikatakan.
Pertama-tama: Jelas kita perlu beberapa definisi di sini. The
InetAddress.getLocalHost().getHostName()
memberikan nama host seperti yang terlihat dari perspektif jaringan . Masalah dengan pendekatan ini didokumentasikan dengan baik dalam jawaban lain: sering membutuhkan pencarian DNS, itu ambigu jika host memiliki beberapa antarmuka jaringan dan itu kadang-kadang gagal kadang-kadang (lihat di bawah).Tetapi pada OS apa pun ada nama lain juga. Nama host yang didefinisikan sangat awal dalam proses boot, jauh sebelum jaringan diinisialisasi. Jendela mengacu pada ini sebagai computername , Linux menyebutnya kernel nama host dan Solaris menggunakan kata nodename . Saya paling suka kata computername , jadi saya akan menggunakan kata itu mulai sekarang.
Menemukan nama pengguna
Di Linux / Unix, computername adalah apa yang Anda dapatkan dari fungsi C
gethostname()
, atauhostname
perintah dari shell atauHOSTNAME
variabel lingkungan di shell mirip Bash.Pada Windows, nama pengguna adalah apa yang Anda dapatkan dari variabel lingkungan
COMPUTERNAME
atauGetComputerName
fungsi Win32 .Java tidak memiliki cara untuk mendapatkan apa yang saya definisikan sebagai 'nama pengguna'. Tentu, ada solusi seperti yang dijelaskan dalam jawaban lain, seperti untuk panggilan Windows
System.getenv("COMPUTERNAME")
, tetapi pada Unix / Linux tidak ada solusi yang baik tanpa menggunakan JNI / JNA atauRuntime.exec()
. Jika Anda tidak keberatan dengan solusi JNI / JNA maka ada gethostname4j yang mati sederhana dan sangat mudah digunakan.Mari kita lanjutkan dengan dua contoh, satu dari Linux dan satu dari Solaris, yang menunjukkan bagaimana Anda dapat dengan mudah masuk ke situasi di mana Anda tidak dapat memperoleh nama pengguna menggunakan metode Java standar.
Contoh Linux
Pada sistem yang baru dibuat, tempat host selama instalasi dinamai 'chicago', kami sekarang mengubah apa yang disebut nama host kernel:
Sekarang nama host kernel adalah 'dallas', seperti yang terlihat dari perintah hostname:
Tapi kita masih punya
Tidak ada kesalahan konfigurasi dalam hal ini. Ini hanya berarti nama jaringan host (atau lebih tepatnya nama antarmuka loopback) berbeda dari nama pengguna host.
Sekarang, coba jalankan
InetAddress.getLocalHost().getHostName()
dan itu akan membuang java.net.UnknownHostException. Anda pada dasarnya terjebak. Tidak ada cara untuk mengambil nilai 'dallas' maupun nilai 'chicago'.Contoh Solaris
Contoh di bawah ini didasarkan pada Solaris 11.3.
Tuan rumah telah sengaja dikonfigurasi sehingga nama loopback <> nama file.
Dengan kata lain kita memiliki:
dan isi / etc / hosts:
dan hasil dari perintah hostname adalah:
Sama seperti pada contoh Linux panggilan ke
InetAddress.getLocalHost().getHostName()
akan gagalSama seperti contoh Linux Anda sekarang terjebak. Tidak ada cara untuk mengambil nilai 'dallas' maupun nilai 'chicago'.
Kapan Anda akan benar-benar berjuang dengan ini?
Sangat sering Anda akan menemukan bahwa
InetAddress.getLocalHost().getHostName()
memang akan mengembalikan nilai yang sama dengan nama pengguna. Jadi tidak ada masalah (kecuali untuk penambahan resolusi nama).Masalahnya muncul biasanya dalam lingkungan PaaS di mana ada perbedaan antara nama pengguna dan nama antarmuka loopback. Misalnya orang melaporkan masalah di Amazon EC2.
Laporan Bug / RFE
Sedikit pencarian mengungkapkan laporan RFE ini: link1 , link2 . Namun, menilai dari komentar pada laporan itu, masalah ini tampaknya telah banyak disalahpahami oleh tim JDK, sehingga tidak mungkin akan ditangani.
Saya suka perbandingan dalam RFE dengan bahasa pemrograman lain.
sumber
Variabel lingkungan juga dapat memberikan cara yang bermanfaat -
COMPUTERNAME
pada Windows,HOSTNAME
pada sebagian besar shell Unix / Linux modern.Lihat: https://stackoverflow.com/a/17956000/768795
Saya menggunakan ini sebagai metode "tambahan" untuk
InetAddress.getLocalHost().getHostName()
, karena seperti yang ditunjukkan beberapa orang, fungsi itu tidak berfungsi di semua lingkungan.Runtime.getRuntime().exec("hostname")
adalah suplemen lain yang mungkin. Pada tahap ini, saya belum menggunakannya.sumber
StringUtils
, itu disediakan oleh proyek commons-lang Apache. Sangat disarankan untuk menggunakannya.System.getenv("HOSTNAME")
keluar nol pada Mac melalui Beanshell untuk Java, tetapiPATH
diekstraksi ok. Saya juga bisa melakukannyaecho $HOSTNAME
di Mac, hanya System.getenv ("HOSTNAME") tampaknya memiliki masalah. Aneh.Cara paling portabel untuk mendapatkan nama host dari komputer saat ini di Jawa adalah sebagai berikut:
sumber
Jika Anda tidak menentang menggunakan dependensi eksternal dari maven central, saya menulis gethostname4j untuk menyelesaikan masalah ini untuk diri saya sendiri. Itu hanya menggunakan JNA untuk memanggil fungsi gethostname libc (atau mendapatkan ComputerName di Windows) dan mengembalikannya kepada Anda sebagai string.
https://github.com/mattsheppard/gethostname4j
sumber
sumber
Hanya lintas satu ... lintas platform (Windows-Linux-Unix-Mac (Unix)) [Selalu berfungsi, Tidak diperlukan DNS]:
Kamu sudah selesai !!
sumber
InetAddress.getLocalHost (). GetHostName () adalah cara terbaik dari keduanya karena ini adalah abstraksi terbaik di tingkat pengembang.
sumber