क्या वास्तव में नोड फ़ाइलों की शुरुआत में "/ usr / bin / env नोड" करता है?


109

मैंने इस लाइन #!/usr/bin/env nodeको कुछ उदाहरणों की शुरुआत में देखा था nodejsऔर मैं बिना किसी ऐसे विषय को खोजे निकल गया था जो उस रेखा के कारण का उत्तर दे सके।

शब्दों की प्रकृति यह खोज करती है कि यह इतना आसान नहीं है।

मैंने हाल ही में कुछ javascriptऔर nodejsकिताबें पढ़ीं और मुझे उनमें से किसी में भी इसे देखना याद नहीं था।

यदि आप एक उदाहरण चाहते हैं, तो आप RabbitMQआधिकारिक ट्यूटोरियल देख सकते हैं , उनके पास इसके लगभग सभी उदाहरण हैं, उनमें से एक है:

#!/usr/bin/env node

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://localhost', function(err, conn) {
  conn.createChannel(function(err, ch) {
    var ex = 'logs';
    var msg = process.argv.slice(2).join(' ') || 'Hello World!';

    ch.assertExchange(ex, 'fanout', {durable: false});
    ch.publish(ex, '', new Buffer(msg));
    console.log(" [x] Sent %s", msg);
  });

  setTimeout(function() { conn.close(); process.exit(0) }, 500);
});

क्या कोई मुझे समझा सकता है कि इस पंक्ति का अर्थ क्या है?

अगर मैं इस लाइन को डालूं या निकालूं तो क्या फर्क पड़ता है? मुझे किन मामलों में इसकी आवश्यकता है?


3
यह मूल रूप से कॉलिंग शेल के वातावरण को लेता है और उस वातावरण को जो भी एप्लिकेशन निर्दिष्ट करता है, उसमें सामान रखता है। इस मामले में,node
मार्क बी

वास्तव में नहीं, मैं विंडोज से नहीं आ रहा हूं, लेकिन आपके उत्तर को अपडेट करने के लिए धन्यवाद। मैं यह देखने के लिए इंतजार कर रहा हूं कि क्या किसी और की राय अलग है। बस एक बात है जो मुझे लगता है कि आपने अपने उत्तर में उल्लेख नहीं किया है, मुझे अभी कुछ घंटे पहले पता चला है। यहां जिन चीजों का वे उल्लेख करते हैं वे महत्वपूर्ण हैं लेकिन यह मेरे लिए अभी तक पर्याप्त नहीं है। stackoverflow.com/questions/14517535/… (यदि आप चाहें तो अपडेट कर सकते हैं, मैं वास्तव में इसे समझूंगा, लेकिन इसे दायित्व की तरह महसूस न करें, आपका जवाब अभी बहुत अच्छा है)।
गेपसर

@Gepser: समझ गया। इसकी कमी यह है: यदि आप npmएक (संभवत: उपलब्ध विश्व स्तर पर) CLI के रूप में Node.js स्रोत स्क्रिप्ट को स्थापित करना चाहते हैं , तो आपको एक शेबंग लाइन का उपयोग करनाnpm होगा - और यहां तक ​​कि विंडोज पर वह काम भी करेगा; मेरे एक बार फिर से अद्यतन जवाब देखें।
mklement0

"शब्दों की प्रकृति यह खोज आसान नहीं बनाती है" - आप इस विशिष्ट खोज उपयोग मामले के लिए duckduckgo.com आज़माना चाहते हैं
रिकार्डो

संभावित डुप्लिकेट क्यों लोग पायथन लिपि की पहली पंक्ति पर #! / Usr / bin / en python shebang लिखते हैं? । एक ही सवाल, विभिन्न दुभाषिया।
jww

जवाबों:


146

#!/usr/bin/env nodeएक शेबबैंग लाइन का एक उदाहरण है : यूनिक्स जैसे प्लेटफार्मों पर एक निष्पादन योग्य सादे-टेक्स्ट फ़ाइल में बहुत पहली पंक्ति जो सिस्टम को बताती है कि जादू की #!उपसर्ग के बाद कमांड लाइन के माध्यम से निष्पादन के लिए उस फ़ाइल को क्या इंटरप्रेटर कहा जाता है (जिसे शेलबैंग कहा जाता है ) ।

नोट: विंडोज शेबंग लाइनों का समर्थन नहीं करता है , इसलिए वे वहां प्रभावी रूप से नजरअंदाज कर रहे हैं; विंडोज पर यह पूरी तरह से एक दिया गया फ़ाइल फ़ाइल नाम एक्सटेंशन है जो यह निर्धारित करता है कि निष्पादन योग्य क्या व्याख्या करेगा। हालाँकि, आपको अभी भी उनके संदर्भ में आवश्यकता हैnpm[1]

शेबंग लाइनों की निम्नलिखित, सामान्य चर्चा यूनिक्स-जैसे प्लेटफार्मों तक सीमित है:

निम्नलिखित चर्चा में मैं मान लूंगा कि Node.js द्वारा निष्पादन के लिए स्रोत कोड वाली फ़ाइल को केवल नाम दिया गया है file

  • आप इस लाइन की आवश्यकता है , अगर आप सीधे अपने आप में एक निष्पादन योग्य के रूप में एक Node.js स्रोत फ़ाइल आह्वान करना चाहते हैं - यह मानता है कि फ़ाइल को एक कमांड के साथ निष्पादन योग्य के रूप में चिह्नित किया गया है chmod +x ./file, जो तब आपको फ़ाइल को लागू करने की अनुमति देता है उदाहरण के लिए, ./fileया, यदि यह $PATHचर में सूचीबद्ध निर्देशिकाओं में से एक में स्थित है , तो बस के रूप में file

    • विशेष रूप से, आपको एक Npm पैकेज के हिस्से के रूप में Node.js स्रोत फ़ाइलों के आधार पर CLIs बनाने के लिए एक Shebang रेखा की आवश्यकता होती है , CLI (s) के साथ पैकेज की फ़ाइल में कुंजी के मूल्य के आधार पर स्थापित किया जाना है ; यह भी देखना यह जवाब कैसे साथ कि काम करता है के लिए विश्व स्तर पर इंस्टॉल किए गए पैकेज। फुटनोट [1] दिखाता है कि यह विंडोज पर कैसे संभाला जाता है।npm"bin"package.json
  • आप ज़रूरत नहीं है स्पष्ट रूप से के माध्यम से एक फ़ाइल को लागू करने की इस लाइन nodeदुभाषिया, जैसे,node ./file


वैकल्पिक पृष्ठभूमि जानकारी :

#!/usr/bin/env <executableName>एक दुभाषिया को आंशिक रूप से निर्दिष्ट करने का एक तरीका है : संक्षेप में, यह कहता है: <executableName>जहाँ भी आप (पहले) इसे $PATHचर में सूचीबद्ध निर्देशिकाओं में पाते हैं (और इसे हाथ में फ़ाइल के लिए पथ से गुजरते हैं ) निष्पादित करें ।

यह इस तथ्य के लिए है कि किसी दिए गए दुभाषिया को प्लेटफार्मों के विभिन्न स्थानों में स्थापित किया जा सकता है, जो निश्चित रूप से node, Node.js द्विआधारी के साथ है।

इसके विपरीत, envउपयोगिता का स्थान स्वयं प्लेटफ़ॉर्म पर एक ही स्थान पर होने से संबंधित हो सकता है , अर्थात् /usr/bin/env- और निष्पादन योग्य के लिए पूर्ण पथ निर्दिष्ट करने के लिए एक शेल्टेन लाइन में आवश्यक है।

ध्यान दें कि POSIX उपयोगिता envकी जा रही है पुनरुद्देशित यहाँ फ़ाइल नाम से पता लगाने और में एक निष्पादन निष्पादित करने के लिए $PATH
इसका असली उद्देश्य envएक आदेश के लिए पर्यावरण का प्रबंधन करना है - envPOSIX कल्पना और कीथ थॉम्पसन के उपयोगी उत्तर देखें


यह भी ध्यान देने योग्य है कि Node.js शेबंग लाइनों के लिए एक वाक्यविन्यास अपवाद बना रहा है , यह देखते हुए कि वे मान्य जावास्क्रिप्ट कोड #नहीं हैं ( POSIX जैसे गोले और अन्य दुभाषियों के विपरीत जावास्क्रिप्ट में एक टिप्पणी चरित्र नहीं है)।


[१] क्रॉस-प्लेटफॉर्म संगति के हित में, पैकेज की फ़ाइल ( संपत्ति के माध्यम से ) में निर्दिष्ट निष्पादन योग्य स्थापित करते समय विंडोज पर रैपर फाइलें (बैच फाइलें) npmबनाता है *.cmd । अनिवार्य रूप से, ये रैपर बैच फाइलें यूनिक्स शेबंग कार्यक्षमता की नकल करते हैं: वे लक्ष्य फ़ाइल को स्पष्ट रूप से शेल्ग लाइन में निर्दिष्ट निष्पादन योग्य के साथ आह्वान करते हैं - इस प्रकार, आपकी स्क्रिप्ट में एक शेलंग लाइन शामिल होनी चाहिए, भले ही आप केवल उन्हें विंडोज पर चलाने का इरादा रखते हों - यह उत्तर देखें विवरण के लिए मेरा। चूंकि फाइलें बिना मंगाई जा सकती हैंpackage.json"bin"
*.cmd.cmdविस्तार, यह एक सहज क्रॉस-प्लेटफॉर्म अनुभव के लिए बनाता है: विंडोज और यूनिक्स दोनों पर आप npmअपने मूल, एक्सटेंशन-कम नाम से प्रभावी रूप से एक अनइंस्टॉल किए गए सीएलआई को लागू कर सकते हैं ।


क्या आप मेरे जैसे डमी के लिए एक स्पष्टीकरण या सारांश प्रदान कर सकते हैं?
एंड्रयू लैम

4
@AndrewLam: विंडोज पर, फाइल एक्सटेंशन जैसे कि .cmdऔर .pyयह निर्धारित करें कि ऐसी फाइलों को निष्पादित करने के लिए किस प्रोग्राम का उपयोग किया जाएगा। यूनिक्स पर, शेबबैंग लाइन उस कार्य को करती है। npmसभी समर्थित प्लेटफ़ॉर्म पर काम करने के लिए , आपको विंडोज पर भी शेलबैंग लाइन की आवश्यकता है।
mklement0

28

एक दुभाषिया द्वारा निष्पादित की जाने वाली लिपियों में आमतौर पर ओएस को बताने के लिए शीर्ष पर एक शबंग रेखा होती है।

यदि आपके पास एक स्क्रिप्ट है fooजिसका नाम पहली पंक्ति है #!/bin/sh, तो सिस्टम उस पहली पंक्ति को पढ़ेगा और उसके बराबर निष्पादित करेगा /bin/sh foo। इस वजह से, अधिकांश व्याख्याकारों को एक स्क्रिप्ट फ़ाइल का नाम कमांड-लाइन तर्क के रूप में स्वीकार करने के लिए स्थापित किया जाता है।

इंटरप्रेटर नाम के बाद #!एक पूर्ण पथ होना चाहिए; ओएस $PATHदुभाषिया खोजने के लिए आपकी खोज नहीं करेगा ।

यदि आपके पास निष्पादित करने के लिए एक स्क्रिप्ट है node, तो पहली पंक्ति लिखने का स्पष्ट तरीका है:

#!/usr/bin/node

लेकिन यह काम नहीं करता है यदि nodeकमांड स्थापित नहीं है /usr/bin

envकमांड का उपयोग करने के लिए एक आम समाधान है (जो वास्तव में इस उद्देश्य के लिए अभिप्रेत नहीं था ):

#!/usr/bin/env node

यदि आपकी स्क्रिप्ट को कॉल किया जाता है foo, तो OS बराबर होगा

/usr/bin/env node foo

envआदेश एक और आदेश जिसका नाम अपने कमांड लाइन पर दिया जाता है कार्यान्वित करता है, कि आदेश के लिए किसी भी निम्नलिखित तर्क गुजर। यहां इसका उपयोग करने का कारण यह है कि कमांड के लिए envखोज करेंगे $PATH। तो अगर आप nodeमें स्थापित है /usr/local/bin/node, और आपके पास /usr/local/binहै $PATH, तो envकमांड आ जाएगी /usr/local/bin/node foo

envकमांड का मुख्य उद्देश्य एक अन्य कमांड को संशोधित वातावरण के साथ निष्पादित करना है, कमांड चलाने से पहले निर्दिष्ट पर्यावरण चर को जोड़ना या निकालना। लेकिन कोई अतिरिक्त तर्क के साथ, यह सिर्फ अपरिवर्तित वातावरण के साथ कमांड को निष्पादित करता है, जो आपको इस मामले में चाहिए।

इस दृष्टिकोण में कुछ कमियां हैं। अधिकांश आधुनिक यूनिक्स जैसी प्रणालियां हैं /usr/bin/env, लेकिन मैंने पुराने सिस्टम पर काम किया है जहां envएक अलग निर्देशिका में कमांड स्थापित किया गया था। अतिरिक्त तर्कों पर सीमाएं हो सकती हैं जिन्हें आप इस तंत्र का उपयोग करके पारित कर सकते हैं। यदि उपयोगकर्ता के पास निर्देशिका नहीं है, जिसमें nodeकमांड है $PATH, या कुछ अलग कमांड है node, तो यह गलत कमांड को लागू कर सकता है या बिल्कुल भी काम नहीं कर सकता है।

अन्य दृष्टिकोण हैं:

  • एक #!लाइन का उपयोग करें जो nodeकमांड के लिए पूर्ण पथ को निर्दिष्ट करता है, स्क्रिप्ट को विभिन्न प्रणालियों के लिए आवश्यकतानुसार अपडेट करता है; या
  • आह्वान nodeएक तर्क के रूप अपनी स्क्रिप्ट वाली आदेश।

चाल की अधिक चर्चा के लिए यह प्रश्न (और मेरा उत्तर ) भी देखें #!/usr/bin/env

संयोग से, मेरे सिस्टम (लिनक्स मिंट 17.2) पर, यह स्थापित है /usr/bin/nodejs। मेरे नोट के अनुसार, यह से बदल /usr/bin/nodeकरने के लिए /usr/bin/nodejsUbuntu 12.04 और 12.10 के बीच। #!/usr/bin/envजब तक आप एक सिमलिंक या कुछ इसी तरह की स्थापना नहीं करते हैं , तो ट्रिक इसकी मदद नहीं करेगी।

अद्यतन: mtraceur द्वारा एक टिप्पणी कहती है (सुधारित):

नोडज बनाम नोड समस्या के लिए एक वर्कअराउंड फ़ाइल को निम्नलिखित छह लाइनों के साथ शुरू करना है:

#!/bin/sh -
':' /*-
test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
test2=$(node --version 2>&1) && exec node "$0" "$@"
exec printf '%s\n' "$test1" "$test2" 1>&2
*/

यह पहले प्रयास करेगा nodejsऔर फिर प्रयास करेगा node, और केवल त्रुटि संदेश मुद्रित करें यदि दोनों नहीं मिले हैं। एक स्पष्टीकरण इन टिप्पणियों के दायरे से बाहर है, मैं इसे यहां छोड़ रहा हूं अगर यह समस्या से किसी को भी निपटने में मदद करता है क्योंकि यह जवाब समस्या को लाया था।

मैंने हाल ही में NodeJS का उपयोग नहीं किया है। मेरे आशा व्यक्त की कि है nodejsबनाम nodeके बाद से मैं पहली बार इस उत्तर पोस्ट मुद्दा वर्षों में हल किया गया है। उबंटू 18.04 पर, nodejsपैकेज सिमिलिंक के /usr/bin/nodejsरूप में स्थापित होता है /usr/bin/node। कुछ पहले के ओएस (उबंटू या लिनक्स मिंट, मुझे यकीन नहीं है कि कौन सा है), एक ऐसा nodejs-legacyपैकेज था nodeजो सिम्लिंक के रूप में प्रदान किया गया था nodejs। कोई गारंटी नहीं है कि मेरे पास सभी विवरण सही हैं।


चीजों के बारे में बहुत गहन जवाब।
सूरज जैन

1
nodejsबनाम nodeसमस्या के लिए एक वैकल्पिक हल निम्नलिखित छह पंक्तियों के साथ फाइल शुरू करना है: 1) #!/bin/sh -, 2) ':' /*-3) test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"4) test2=$(node --version 2>&1) && exec node "$0" "$@", 5) exec printf '%s\n' "$test1" "$test2" 1>&26) */। यह पहले प्रयास करेगा nodejsऔर फिर प्रयास करेगा node, और केवल त्रुटि संदेश मुद्रित करें यदि दोनों नहीं मिले हैं। एक स्पष्टीकरण इन टिप्पणियों के दायरे से बाहर है, मैं इसे यहां छोड़ रहा हूं अगर यह समस्या से किसी को भी निपटने में मदद करता है क्योंकि यह उत्तर समस्या को लाया था।
मृत्युंजय

@mtraceur: मैंने आपकी टिप्पणी को अपने उत्तर में शामिल कर लिया है। लाइन -पर क्यों #!?
कीथ थॉम्पसन

-में #!/bin/sh -सिर्फ एक आदत सुनिश्चित करती है कि खोल बर्ताव सही अत्यंत संकीर्ण और संभावना नहीं परिस्थितियों के सेट है कि स्क्रिप्ट नाम या रिश्तेदार रास्ता है कि खोल एक साथ शुरू होता है देखता है -। (इसके अलावा, हाँ, ऐसा लगता है कि हर मुख्यधारा का डिस्ट्रो वापस nodeप्राथमिक नाम के रूप में परिवर्तित हो गया था । मैं अपनी टिप्पणी करते समय जाँच करने के लिए खुदाई करने नहीं गया था, लेकिन जहाँ तक मुझे पता है कि केवल डेबियन डिस्ट्रो परिवार के पेड़ का उपयोग किया जाता है nodejs, और यह दिखता है जैसा कि वे सभी nodeडेबियन के एक बार समर्थन करने के लिए वापस लौट आए ।)
mtraceur

तकनीकी रूप से पहले तर्क के रूप में एकल डैश का अर्थ "विकल्पों का अंत" नहीं था - इसका मूल अर्थ "बंद करना " -xऔर था -v, लेकिन शुरुआती बॉर्न-लाइक्स के बाद से ही संभव विकल्पों के रूप में पहला तर्क आया, और चूंकि शेल उन विकल्पों से शुरू होता है। , यह मूल के बाद से स्क्रिप्ट नाम को पार्स करने की कोशिश नहीं करने के कारण शेल को अपमानजनक था, और इस तरह से अपमानजनक बना हुआ है क्योंकि संगतता कारणों के लिए आधुनिक बॉर्न-लाइक में व्यवहार बनाए रखा जाता है। अगर मुझे अपना सारा बॉर्न इतिहास और पोर्टेबिलिटी ट्रिविया सही याद है।
मत्तुर

0

संक्षिप्त उत्तर: यह दुभाषिया का मार्ग है।

EDIT (दीर्घ उत्तर): "नोड" से पहले स्लैश नहीं होने का कारण यह है कि आप हमेशा # / / / / की विश्वसनीयता की गारंटी नहीं दे सकते। "/ Env" बिट एक संशोधित वातावरण में स्क्रिप्ट को चलाकर कार्यक्रम को अधिक क्रॉस-प्लेटफॉर्म बनाता है और अधिक मज़बूती से दुभाषिया कार्यक्रम को खोजने में सक्षम होता है।

आपको इसकी आवश्यकता नहीं है, लेकिन पोर्टेबिलिटी (और व्यावसायिकता) सुनिश्चित करने के लिए इसका उपयोग करना अच्छा है


1
/usr/bin/envबिट वातावरण संशोधित नहीं करता है। यह सिर्फ (ज्यादातर) ज्ञात स्थान पर एक कमांड है जो एक तर्क के रूप में दिए गए दूसरे कमांड को आमंत्रित करता है, और $PATHइसे खोजने के लिए खोज करता है। मुद्दा यह है कि #!लाइन को कमांड के लिए पूर्ण पथ की आवश्यकता होती है, और आपको यह नहीं पता है कि कहां nodeस्थापित है।
कीथ थॉम्पसन

यही तो मैं जा रहा था, स्पष्ट करने के लिए धन्यवाद!
क्वांटम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.