जावा में वर्तमान कंप्यूटर का होस्टनाम प्राप्त करने के लिए निम्नलिखित में से कौन सा सबसे अच्छा और सबसे पोर्टेबल तरीका है?
Runtime.getRuntime().exec("hostname")
बनाम
InetAddress.getLocalHost().getHostName()
जावा में वर्तमान कंप्यूटर का होस्टनाम प्राप्त करने के लिए निम्नलिखित में से कौन सा सबसे अच्छा और सबसे पोर्टेबल तरीका है?
Runtime.getRuntime().exec("hostname")
बनाम
InetAddress.getLocalHost().getHostName()
जवाबों:
सख्ती से बोलना - आपके पास hostname(1)
यूनिक्स पर या तो कॉल करने के अलावा कोई विकल्प नहीं है gethostname(2)
। यह आपके कंप्यूटर का नाम है। इस तरह एक आईपी पते द्वारा hostname निर्धारित करने का कोई भी प्रयास
InetAddress.getLocalHost().getHostName()
कुछ परिस्थितियों में विफल होने के लिए बाध्य है:
होस्ट (होस्टनाम) के नाम के साथ आईपी-पते के नाम को भी भ्रमित न करें। एक रूपक इसे स्पष्ट कर सकता है:
एक बड़ा शहर (सर्वर) है जिसे "लंदन" कहा जाता है। शहर की दीवारों के अंदर बहुत व्यापार होता है। शहर में कई द्वार (आईपी पते) हैं। प्रत्येक गेट का एक नाम ("नॉर्थ गेट", "रिवर गेट", "साउथेम्प्टन गेट" ...) है, लेकिन गेट का नाम शहर का नाम नहीं है। इसके अलावा, आप एक गेट के नाम का उपयोग करके शहर का नाम नहीं काट सकते हैं - "नॉर्थ गेट" बड़े शहरों में से आधे को पकड़ लेगा और न केवल एक शहर को। हालांकि - एक अजनबी (आईपी पैकेट) नदी के किनारे चलता है और एक स्थानीय से पूछता है: "मेरे पास एक अजीब पता है: 'रिवरगेट, दूसरे बाएं, तीसरे घर'। क्या आप मेरी मदद कर सकते हैं?" स्थानीय कहते हैं: "बेशक, आप सही रास्ते पर हैं, बस आगे बढ़ें और आप आधे घंटे के भीतर अपने गंतव्य पर पहुंच जाएंगे।"
यह मुझे लगता है कि यह बहुत दिखाता है।
अच्छी खबर यह है: असली मेजबाननाम आमतौर पर आवश्यक नहीं होता है। ज्यादातर मामलों में कोई भी नाम जो इस मेजबान पर एक आईपी पते में हल होता है। (अजनबी नॉर्थगेट द्वारा शहर में प्रवेश कर सकता है, लेकिन सहायक स्थानीय लोग "2 के बाएं" भाग का अनुवाद करते हैं।)
यदि शेष कोने के मामले आपको इस कॉन्फ़िगरेशन सेटिंग के निश्चित स्रोत का उपयोग करना चाहिए - जो कि सी फ़ंक्शन है gethostname(2)
। उस फ़ंक्शन को प्रोग्राम द्वारा भी बुलाया जाता है hostname
।
InetAddress.getLocalHost().getHostName()
अधिक पोर्टेबल तरीका है।
exec("hostname")
वास्तव में hostname
कमांड को निष्पादित करने के लिए ऑपरेटिंग सिस्टम को कॉल करता है ।
यहाँ SO पर कुछ अन्य संबंधित उत्तर दिए गए हैं:
संपादित करें: आपको अपनी स्थिति के आधार पर एएच के जवाब या अर्नौट एंगेलन के विवरण के बारे में जानकारी लेनी चाहिए कि यह अपेक्षा के अनुरूप काम क्यों नहीं कर सकता है। इस व्यक्ति के लिए एक उत्तर के रूप में, जिसने विशेष रूप से पोर्टेबल का अनुरोध किया था, मुझे अभी भी getHostName()
ठीक लगता है, लेकिन वे कुछ अच्छे बिंदु लाते हैं, जिन पर विचार किया जाना चाहिए।
InetAddress.getLocalHost()
कुछ मामलों में लूपबैक डिवाइस लौटाता है। उस मामले में, getHostName()
"लोकलहोस्ट" लौटाता है, जो बहुत उपयोगी नहीं है।
जैसा कि अन्य ने उल्लेख किया है, DNS रिज़ॉल्यूशन के आधार पर होस्टनाम प्राप्त करना अविश्वसनीय है।
चूंकि यह सवाल दुर्भाग्य से 2018 में अभी भी प्रासंगिक है , मैं आपके साथ अपने नेटवर्क-स्वतंत्र समाधान को साझा करना चाहूंगा, विभिन्न प्रणालियों पर कुछ परीक्षण रन के साथ।
निम्नलिखित कोड निम्नलिखित करने की कोशिश करता है:
विंडोज पर
COMPUTERNAME
पर्यावरण चर के माध्यम से पढ़ें System.getenv()
।
निष्पादित करें hostname.exe
और प्रतिक्रिया पढ़ें
लिनक्स पर
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:""
ओपनस्यूज 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 LTS
यह echo $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
"
EDIT: लेगोलास108 के अनुसार , System.getenv("HOSTNAME")
अगर आप export HOSTNAME
जावा कोड को निष्पादित करने से पहले चलाते हैं, तो यह 14.04 Ubuntu पर काम करता है ।
विंडोज 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 पर जावा कोड चलाने से पहले इसे लौटाते हैं System.getenv("HOSTNAME")
।
export HOSTNAME
जावा का स्पष्ट रूप से उपयोग करना है? मुझे लगा कि इसे PATH की तरह एक डिफ़ॉल्ट env var होना चाहिए।
\A
सीमांकक पूरी इनपुटस्ट्रीम का उपयोग कर पढ़ने के लिए एक हैक है Scanner
।
InetAddress.getLocalHost().getHostName()
बेहतर है (जैसा कि निक द्वारा समझाया गया है), लेकिन फिर भी बहुत अच्छा नहीं है
एक मेजबान को कई अलग-अलग होस्टनामों के तहत जाना जा सकता है। आमतौर पर आप होस्टनाम की तलाश में होंगे जो आपके होस्ट ने एक विशिष्ट संदर्भ में है।
उदाहरण के लिए, एक वेब एप्लिकेशन में, आप उस होस्टनाम की तलाश कर सकते हैं जिसका उपयोग आपने उस अनुरोध को जारी किया है जिसे आप वर्तमान में संभाल रहे हैं। सबसे अच्छा यह कैसे पता लगाएं कि आप अपने वेब एप्लिकेशन के लिए किस फ्रेमवर्क का उपयोग कर रहे हैं।
किसी अन्य प्रकार की इंटरनेट-फ़ेसिंग सेवा में, आप चाहते हैं कि होस्टनाम आपकी सेवा 'बाहर' से उपलब्ध हो। परदे के पीछे, फ़ायरवॉल आदि के कारण यह भी नहीं हो सकता है कि जिस मशीन पर आपकी सेवा स्थापित है, उस पर एक होस्टनाम नहीं है - आप एक उचित डिफ़ॉल्ट के साथ आने की कोशिश कर सकते हैं, लेकिन आपको इसे स्थापित करने वाले के लिए निश्चित रूप से यह विन्यास करना चाहिए।
हालाँकि इस विषय पर पहले ही उत्तर दिया जा चुका है।
सबसे पहले: स्पष्ट रूप से हमें यहां कुछ परिभाषाओं की आवश्यकता है। InetAddress.getLocalHost().getHostName()
आप होस्ट का नाम देता है के रूप में एक नेटवर्क के नजरिए से देखा । इस दृष्टिकोण के साथ समस्याओं को अन्य उत्तरों में अच्छी तरह से प्रलेखित किया गया है: इसे अक्सर एक DNS लुकअप की आवश्यकता होती है, यह अस्पष्ट है यदि होस्ट में कई नेटवर्क इंटरफेस हैं और यह बस कभी-कभी विफल होता है (नीचे देखें)।
लेकिन किसी भी ओएस पर एक और नाम भी है। होस्ट का एक नाम जो बूट प्रक्रिया में बहुत पहले परिभाषित हो जाता है, नेटवर्क शुरू होने से बहुत पहले। विंडोज इसे कंप्यूटर के रूप में संदर्भित करता है , लिनक्स इसे कर्नेल होस्टनाम कहता है और सोलारिस नोडनैम शब्द का उपयोग करता है । मुझे सबसे अच्छा शब्द कॉम्पुटरनेम पसंद है , इसलिए मैं अब से उस शब्द का उपयोग करूंगा।
लिनक्स / यूनिक्स पर कम्प्यूटेशन वह है जो आप सी फ़ंक्शन से प्राप्त करते हैं gethostname()
, या बैश-जैसे शेल में hostname
शेल या HOSTNAME
पर्यावरण चर से कमांड करते हैं।
विंडोज पर कंप्यूटर का नाम वह है जो आपको पर्यावरण चर COMPUTERNAME
या Win32 GetComputerName
फ़ंक्शन से मिलता है ।
जावा के पास वह तरीका नहीं है जिसे मैंने 'कम्प्यूट्यूटनाम' के रूप में परिभाषित किया है। निश्चित रूप से, विंडोज कॉलिंग के लिए, जैसे अन्य उत्तरों में वर्णित वर्कअराउंड हैं System.getenv("COMPUTERNAME")
, लेकिन यूनिक्स / लिनक्स पर जेएनआई / जेएनए का सहारा लिए बिना कोई अच्छा समाधान नहीं है Runtime.exec()
। यदि आपको जेएनआई / जेएनए समाधान से कोई आपत्ति नहीं है, तो इसमें gethostname4j है जो मृत सरल है और उपयोग करने में बहुत आसान है।
आइए दो उदाहरणों के साथ चलते हैं, एक लिनक्स से और एक सोलारिस से, जो प्रदर्शित करता है कि आप आसानी से ऐसी स्थिति में कैसे पहुँच सकते हैं जहाँ आप मानक जावा विधियों का उपयोग करके संगणना प्राप्त नहीं कर सकते।
एक नई बनाई गई प्रणाली पर, जहां इंस्टालेशन के दौरान होस्ट को 'चिकोटेगो' नाम दिया गया है, अब हम तथाकथित ko होस्टनाम को बदलते हैं:
$ 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.UnognHostException को फेंक देगा। आप मूल रूप से फंस गए हैं। वहाँ न तो 'डलास' मान और न ही 'chicago' मान प्राप्त करने का कोई तरीका नहीं है।
नीचे दिया गया उदाहरण सोलारिस 11.3 पर आधारित है।
होस्ट को जानबूझकर कॉन्फ़िगर किया गया है ताकि लूपबैक नाम <> नोडेनम हो।
दूसरे शब्दों में हमारे पास:
$ svccfg -s system/identity:node listprop config
...
...
config/loopback astring chicago
config/nodename astring dallas
और / etc / मेजबान की सामग्री:
:1 chicago localhost
127.0.0.1 chicago localhost loghost
और hostname कमांड का परिणाम होगा:
$ hostname
dallas
लिनक्स में जैसे उदाहरण के InetAddress.getLocalHost().getHostName()
साथ कॉल विफल हो जाएगा
java.net.UnknownHostException: dallas: dallas: node name or service name not known
लिनक्स उदाहरण की तरह अब आप फंस गए हैं। वहाँ न तो 'डलास' मान और न ही 'chicago' मान प्राप्त करने का कोई तरीका नहीं है।
बहुत बार आप पाएंगे कि InetAddress.getLocalHost().getHostName()
वास्तव में एक मूल्य वापस आएगा जो कि संगणना के बराबर है। तो कोई समस्या नहीं है (नाम समाधान के अतिरिक्त उपरि को छोड़कर)।
समस्या आमतौर पर PaaS के वातावरण में उत्पन्न होती है, जहाँ कंप्यूट नाम और लूपबैक इंटरफ़ेस के नाम में अंतर होता है। उदाहरण के लिए लोग Amazon EC2 में समस्याओं की रिपोर्ट करते हैं।
खोज का एक बिट इस RFE रिपोर्ट से पता चलता है: link1 , link2 । हालाँकि, उस रिपोर्ट पर टिप्पणियों को देखते हुए लगता है कि इस मुद्दे को JDK टीम ने काफी हद तक गलत समझा है, इसलिए इसकी संभावना नहीं है कि इसे संबोधित किया जाएगा।
मुझे RFE में अन्य प्रोग्रामिंग भाषाओं की तुलना पसंद है।
अधिकांश आधुनिक यूनिक्स / लिनक्स गोले पर COMPUTERNAME
, विंडोज पर पर्यावरण चर भी एक उपयोगी साधन प्रदान कर सकते हैं HOSTNAME
।
देखें: 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
, तो यह अपाचे कॉमन्स-लैंग परियोजना द्वारा प्रदान किया गया है। इसका उपयोग करना, या ऐसा कुछ करना, अत्यधिक अनुशंसित है।
System.getenv("HOSTNAME")
जावा के लिए बीन्सहेल के माध्यम से मैक पर शून्य निकला, लेकिन PATH
ठीक निकाला गया था। मैं echo $HOSTNAME
मैक पर भी कर सकता था, बस System.getenv ("HOSTNAME") में समस्या है। अजीब।
जावा में वर्तमान कंप्यूटर का होस्टनाम प्राप्त करने का सबसे पोर्टेबल तरीका इस प्रकार है:
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);
}
}
यदि आप मावेन सेंट्रल से बाहरी निर्भरता का उपयोग करने के खिलाफ नहीं हैं, तो मैंने अपने लिए इस समस्या को हल करने के लिए gethostname4j लिखा। यह सिर्फ जेबीए का उपयोग लिबास के गेटहोस्टनाम फ़ंक्शन को कॉल करने के लिए करता है (या विंडोज पर कंप्यूटरनाम प्राप्त करता है) और इसे एक स्ट्रिंग के रूप में आपको लौटाता है।
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();
}
}
}
}
बस एक-लाइनर ... क्रॉस प्लेटफ़ॉर्म (विंडोज-लिनक्स-यूनिक्स-मैक (यूनिक्स)) [हमेशा काम करता है, कोई DNS आवश्यक नहीं है]:
String hostname = new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))
.readLine();
हो गया !!
InetAddress.getLocalHost ()। GetHostName () दो में से सबसे अच्छा तरीका है क्योंकि यह डेवलपर स्तर पर सबसे अच्छा अमूर्त है।