बैश स्क्रिप्ट के हेडर में, उन दो कथनों में क्या अंतर है:
#!/usr/bin/env bash#!/usr/bin/bash
जब मैंने env मैन पेज पर सलाह ली , तो मुझे यह परिभाषा मिली:
env - run a program in a modified environment
इसका क्या मतलब है?
बैश स्क्रिप्ट के हेडर में, उन दो कथनों में क्या अंतर है:
#!/usr/bin/env bash
#!/usr/bin/bash
जब मैंने env मैन पेज पर सलाह ली , तो मुझे यह परिभाषा मिली:
env - run a program in a modified environment
इसका क्या मतलब है?
जवाबों:
के माध्यम से एक कमांड चलाने से /usr/bin/envप्रोग्राम के डिफ़ॉल्ट संस्करण में जो कुछ भी है उसे आपके वर्तमान एनवी आयरनमेंट में देखने का लाभ है।
इस तरह, आपको सिस्टम पर एक विशिष्ट स्थान पर देखने की ज़रूरत नहीं है, क्योंकि वे पथ अलग-अलग सिस्टम पर अलग-अलग स्थानों में हो सकते हैं। जब तक यह आपके रास्ते में है, यह इसे खोज लेगा।
एक नकारात्मक पक्ष यह है कि आप एक से अधिक तर्क पारित करने में असमर्थ होंगे (जैसे कि आप लिखने में असमर्थ होंगे /usr/bin/env awk -f) यदि आप लिनक्स का समर्थन करना चाहते हैं, क्योंकि पोसिक्स अस्पष्ट है कि लाइन की व्याख्या कैसे की जाती है, और लिनक्स पहले के बाद सब कुछ व्याख्या करता है। एक भी तर्क निरूपित करने के लिए स्थान। आप इसके चारों ओर पाने /usr/bin/env -Sके envलिए कुछ संस्करणों पर उपयोग कर सकते हैं , लेकिन फिर स्क्रिप्ट कम पोर्टेबल हो जाएगी और हाल ही में सिस्टम पर टूट जाएगी (उदाहरण के लिए Ubuntu 16.04 बाद में नहीं तो)।
एक और नकारात्मक पहलू यह है कि चूंकि आप एक स्पष्ट निष्पादन योग्य फोन नहीं कर रहे हैं, इसलिए यह गलतियों के लिए संभावित है, और बहुउद्देशीय सिस्टम सुरक्षा समस्याओं पर (यदि कोई bashआपके निष्पादन योग्य को अपने पथ में प्राप्त करने में कामयाब रहा , उदाहरण के लिए)।
#!/usr/bin/env bash #lends you some flexibility on different systems
#!/usr/bin/bash #gives you explicit control on a given system of what executable is called
कुछ स्थितियों में, पहले को प्राथमिकता दी जा सकती है (जैसे कि निष्पादन योग्य लाइन को फिर से काम करने के बिना, अजगर के कई संस्करणों के साथ अजगर स्क्रिप्ट चलाना)। लेकिन उन स्थितियों में जहां सुरक्षा ध्यान केंद्रित है, बाद वाले को प्राथमिकता दी जाएगी, क्योंकि यह कोड इंजेक्शन संभावनाओं को सीमित करता है।
#!/usr/bin/env echo Helloशिकायत करता है /usr/bin/env: echo Hello: No such file or directory:। जाहिरा तौर पर यह echo Helloएक ही तर्क के रूप में व्यवहार करता है /usr/bin/env।
envकमांड निश्चित रूप से कमांड को पास करने के लिए तर्क देता है। मुद्दा #!पंक्ति का शब्दार्थ है , और जो कर्नेल पर निर्भर करता है। हाल ही में लिनक्स कर्नेल जैसी चीजों की अनुमति देते हैं #!/usr/bin/env command args, लेकिन पुराने लिनक्स कर्नेल और अन्य सिस्टम नहीं करते हैं।
#!/usr/bin/env NAME$ PATH पर्यावरण चर में NAME के पहले मैच के लिए शेल खोज का उपयोग करता है। यह उपयोगी हो सकता है यदि आप निरपेक्ष पथ के बारे में नहीं जानते हैं या इसके लिए खोज नहीं करना चाहते हैं।
/usr/bin/bash/एनवी कमांड के रूप में , दुभाषिया के लिए मार्ग को स्पष्ट रूप से परिभाषित करने के बजाय , दुभाषिया की खोज की जाती है और जहां भी यह पहली बार पाया जाता है, वहां से लॉन्च किया जाता है। इसमें उतार-चढ़ाव दोनों होते हैं
यदि शेल स्क्रिप्ट शुरू होती हैं #!/bin/bash, तो वे हमेशा साथ bashसे चलेंगी /bin। अगर वे फिर भी साथ शुरू #!/usr/bin/env bash, वे के लिए खोज करेंगे bashमें $PATHऔर फिर पहले एक वे प्राप्त कर सकते के साथ शुरू करते हैं।
यह क्यों उपयोगी होगा? मान लें कि आप bashस्क्रिप्ट्स चलाना चाहते हैं, जिसके लिए bash 4.x या नए की आवश्यकता है, फिर भी आपके सिस्टम में केवल bash3.x इंस्टॉल है और वर्तमान में आपका वितरण एक नया संस्करण प्रदान नहीं करता है या आप कोई व्यवस्थापक नहीं हैं और उस सिस्टम पर इंस्टॉल किए गए को परिवर्तित नहीं कर सकते हैं। ।
बेशक, आप bash source कोड डाउनलोड कर सकते हैं और अपने खुद के bash को खरोंच से बना सकते हैं, ~/binउदाहरण के लिए। और आप पहली प्रविष्टि के रूप में शामिल करने के लिए $PATHअपनी .bash_profileफ़ाइल में अपने चर को भी संशोधित कर सकते हैं ~/bin( PATH=$HOME/bin:$PATHजैसा ~कि विस्तार नहीं होगा $PATH)। यदि आप अब कॉल करते हैं bash, तो शेल पहले इसे $PATHक्रम में खोजेगा, इसलिए यह इसके साथ शुरू होता है ~/bin, जहां यह आपकी खोज करेगा bash। अगर स्क्रिप्ट bashका उपयोग करने के लिए खोज होती है, तो एक ही बात होती है #!/usr/bin/env bash, इसलिए ये स्क्रिप्ट अब आपके कस्टम bashबिल्ड का उपयोग करके आपके सिस्टम पर काम करेगी ।
एक नकारात्मक पक्ष यह है कि इससे अप्रत्याशित व्यवहार हो सकता है, उदाहरण के लिए एक ही मशीन पर एक ही स्क्रिप्ट अलग-अलग वातावरणों या उपयोगकर्ताओं के लिए अलग-अलग खोज पथों के साथ विभिन्न दुभाषियों के साथ चल सकती है, जिससे सभी तरह के सिरदर्द हो सकते हैं।
इसके साथ सबसे बड़ा नकारात्मक यह envहै कि कुछ सिस्टम केवल एक तर्क की अनुमति देंगे, इसलिए आप ऐसा नहीं कर सकते #!/usr/bin/env <interpreter> <arg>, क्योंकि सिस्टम <interpreter> <arg>एक तर्क के रूप में देखेंगे (वे इसे मानेंगे जैसे कि अभिव्यक्ति उद्धृत की गई थी) और इस प्रकार envनाम की व्याख्या करने वाले की खोज करेंगे <interpreter> <arg>। ध्यान दें कि यह envअपने आप में कमांड की समस्या नहीं है, जो हमेशा कई मापदंडों से गुजरने की अनुमति देता है, लेकिन सिस्टम के शेबंग पार्सर के साथ भी जो कॉल करने से पहले इस लाइन को पार्स करता है env। इस बीच यह अधिकांश प्रणालियों पर तय किया गया है, लेकिन अगर आपकी स्क्रिप्ट अल्ट्रा पोर्टेबल होना चाहती है, तो आप भरोसा नहीं कर सकते कि यह उस सिस्टम पर तय किया गया है जिसे आप चला रहे हैं।
यहां तक कि इसमें सुरक्षा निहितार्थ भी हो सकते हैं, उदाहरण के लिए यदि sudoस्वच्छ वातावरण में कॉन्फ़िगर नहीं किया $PATHगया था या सफाई से बाहर रखा गया था। मुझे इसे प्रदर्शित करें:
आमतौर /binपर एक अच्छी तरह से संरक्षित जगह है, केवल rootवहाँ कुछ भी बदलने में सक्षम है। आपके घर की निर्देशिका, हालांकि, आपके द्वारा चलाया गया कोई भी कार्यक्रम इसमें परिवर्तन करने में सक्षम नहीं है। इसका मतलब है कि दुर्भावनापूर्ण कोड bashकुछ छिपा निर्देशिका में एक नकली जगह ले सकता है , .bash_profileउस निर्देशिका को अपने में शामिल करने के लिए संशोधित कर सकता है $PATH, इसलिए उपयोग करने वाली सभी स्क्रिप्ट #!/usr/bin/env bashउस नकली के साथ चल रही हैं bash। अगर sudoरखता है $PATH, तो आप बड़ी मुसीबत में हैं।
उदाहरण के लिए एक उपकरण ~/.evil/bashनिम्नलिखित सामग्री के साथ एक फ़ाइल बनाता है:
#!/bin/bash
if [ $EUID -eq 0 ]; then
echo "All your base are belong to us..."
# We are root - do whatever you want to do
fi
/bin/bash "$@"
चलो एक सरल स्क्रिप्ट बनाते हैं sample.sh:
#!/usr/bin/env bash
echo "Hello World"
अवधारणा का सबूत (एक प्रणाली पर जहाँ sudoरखता है $PATH):
$ ./sample.sh
Hello World
$ sudo ./sample.sh
Hello World
$ export PATH="$HOME/.evil:$PATH"
$ ./sample.sh
Hello World
$ sudo ./sample.sh
All your base are belong to us...
Hello World
आम तौर पर क्लासिक गोले सभी में स्थित होने चाहिए /binऔर यदि आप उन्हें किसी भी कारण से वहां नहीं रखना चाहते हैं, तो यह वास्तव में /binउनके वास्तविक स्थानों (या शायद /binखुद एक सिम्लिंक) को इंगित करने के लिए सिम्लिंक लगाने का मुद्दा नहीं है , इसलिए मैं हमेशा साथ जाता #!/bin/shऔर #!/bin/bash। वहाँ सिर्फ इतना है कि अगर ये अब और काम नहीं करेगा तो टूट जाएगा। ऐसा नहीं है कि POSIX को इन स्थिति की आवश्यकता होगी (POSIX पथ नामों को मानकीकृत नहीं करता है और इस प्रकार यह शेलबैंग फीचर को बिल्कुल भी मानकीकृत नहीं करता है), लेकिन वे इतने सामान्य हैं, कि भले ही कोई सिस्टम एक प्रस्ताव नहीं देगा /bin/sh, यह शायद समझ जाएगा #!/bin/shऔर पता है कि इसके साथ क्या करना है और यह केवल मौजूदा कोड के साथ संगतता के लिए हो सकता है।
लेकिन अधिक आधुनिक, गैर मानक, पर्ल, पीएचपी, पायथन या रूबी जैसे वैकल्पिक दुभाषियों के लिए, यह वास्तव में कहीं भी निर्दिष्ट नहीं है जहां उन्हें स्थित होना चाहिए। वे में हो सकता है /usr/bin, लेकिन वे के रूप में अच्छी में हो सकता है /usr/local/binया एक पूरी तरह से अलग पदानुक्रम शाखा (में /opt/..., /Applications/..., आदि)। यही कारण है कि ये अक्सर #!/usr/bin/env xxxशेबांग सिंटैक्स का उपयोग करते हैं ।
मुझे यह उपयोगी लगता है, क्योंकि जब मुझे एनवी के बारे में नहीं पता था, तो स्क्रिप्ट लिखने से पहले मैं यह कर रहा था:
type nodejs > scriptname.js #or any other environment
और फिर मैं फ़ाइल में उस पंक्ति को शबंग में संशोधित कर रहा था।
मैं यह कर रहा था, क्योंकि मुझे हमेशा याद नहीं था कि मेरे कंप्यूटर पर नोडज कहां है - / usr / bin / या / bin /, इसलिए मेरे envलिए बहुत उपयोगी है। शायद इसके साथ विवरण हैं, लेकिन यह मेरा कारण है