बैश स्क्रिप्ट के हेडर में, उन दो कथनों में क्या अंतर है:
#!/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 या नए की आवश्यकता है, फिर भी आपके सिस्टम में केवल bash
3.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
लिए बहुत उपयोगी है। शायद इसके साथ विवरण हैं, लेकिन यह मेरा कारण है