#? / Usr / bin / env bash # से बेहतर क्यों है? / बिन / बैश?


212

मैंने इस स्थान पर सिफारिशों सहित कई स्थानों पर देखा है ( वरीयता में बैश शेबंग क्या है? ), #!/usr/bin/env bashवरीयता में उपयोग करने के लिए #!/bin/bash। मैंने भी देखा है कि एक व्यक्ति ने सुझाव देते हुए #!/bin/bashकहा कि यह गलत था और ऐसा करने से कार्यक्षमता खो जाएगी।

सभी ने कहा, मैं कसकर नियंत्रित परीक्षण वातावरण में बैश का उपयोग करता हूं जहां संचलन में प्रत्येक ड्राइव अनिवार्य रूप से एकल मास्टर ड्राइव का क्लोन है। मैं पोर्टेबिलिटी के तर्क को समझता हूं, हालांकि यह मेरे मामले में जरूरी नहीं है। क्या #!/usr/bin/env bashविकल्प को पसंद करने का कोई और कारण है और पोर्टेबिलिटी को एक चिंता का विषय मान लेना, क्या इसका उपयोग कार्यक्षमता को तोड़ सकता है?


7
यह बेहतर नहीं है जरूरी है। इस सवाल और unix.stackexchange.com पर मेरा जवाब देखें । (मैं इसे एक डुप्लिकेट के रूप में बंद करने के लिए मतदान करूंगा, लेकिन मुझे नहीं लगता कि आप साइटों पर ऐसा कर सकते हैं।)
कीथ थॉम्पसन

2
@ Zigg के उत्तर के अलावा, envपर स्थित नहीं हो सकता है /usr/bin। शेबांग टिप्पणी पूरी तरह से एक बुरा विचार है IMHO। यदि आपकी डिफ़ॉल्ट स्क्रिप्ट दुभाषिया शेबंग टिप्पणियों को संभालती नहीं है, तो यह केवल एक टिप्पणी है। हालाँकि, यदि आप जानते हैं कि स्क्रिप्ट दुभाषिया शेबंग टिप्पणियों को संभाल सकता है, और आप को पता चल सकता है, कि कोई रास्ता नहीं है, तो इसके पूर्ण पथ का उपयोग करने के लिए इसे लागू न करने का कोई कारण नहीं है जब तक कि मार्ग बहुत लंबा (संभावनाहीन) नहीं है, या आप संभवतः स्क्रिप्ट को पोर्ट कर सकते हैं एक ऐसी प्रणाली जिसमें bash / bin में स्थित नहीं है। फिर, मेरे द्वारा पूर्व में उल्लिखित कैविएट उस मामले में लागू होते हैं क्योंकि इसमें पोर्टेबिलिटी शामिल है।

1
@KeithThompson, लिंक के लिए धन्यवाद। शायद सवाल पोस्ट करने से पहले एक जवाब के लिए मेरी खोज थोड़ी संकीर्ण थी। इस सब से मेरा दूर-दूर: (1) linux / unix / posix / etc ... ग्रे है, और (2) किसी को भी बिल्कुल सही उत्तर देने का दावा करने वाले के पास अपने विशेष परिदृश्य के लिए सही उत्तर है।
spugm1r3

3
POSIX / Unix में कई चीजों के व्यवहार को अच्छी तरह से परिभाषित किया गया है। स्थान हमेशा इतने स्पष्ट नहीं होते हैं। Somethings की तरह मौजूद है /etcया /bin/shbashसिस्टम जैसे अधिकांश यूनिक्स के लिए एक ऐड-ऑन है। यह केवल लिनक्स है जहां होने bashकी गारंटी है /binऔर सबसे अधिक संभावना भी है /bin/sh। चूंकि लिनक्स बहुत से लोगों के लिए आधुनिक डी तथ्य यूनिक्स बन गया है, इसलिए तथ्य यह है कि लिनक्स के अलावा अन्य सिस्टम मौजूद हो सकते हैं। नीचे मेरे अपने जवाब में मैंने लिनक्स को ग्रहण किया क्योंकि आपने कहा था bash। मैंने जितने भी BSD बॉक्स के साथ काम किया है, उनमें से एक भी स्थापित नहीं किया है।
शॉन पेरी

2
@ कीथ - बैश के मामले में (अन्य प्रश्नों में अजगर के विपरीत) ... ओपनबीडी में नहीं है /bin/bash। मूलभूत रूप से बैश स्थापित नहीं है। यदि आप यह चाहते हैं, तो आपको करना होगा pkg install bash। एक बार स्थापित होने के बाद यह स्थित है /usr/local/bin/bash/bin/bashOpenBSD पर कुछ भी स्थापित नहीं है । #!/bin/bashत्रुटि का एक गड़बड़ी, और #!/usr/bin/env bashसफल होगा।
jww

जवाबों:


229

#!/usr/bin/envविशेष रूप से नॉन-लिनक्स सिस्टम पर हमेशा खोज करता PATHहै bash, और bashमें नहीं है /bin। उदाहरण के लिए, मेरे OpenBSD सिस्टम पर, यह /usr/local/binएक वैकल्पिक पैकेज के रूप में स्थापित होने के बाद से है।

यदि आप पूरी तरह कर रहे हैं यकीन है कि bashमें है /binऔर हमेशा रहेंगे, वहाँ यह सीधे अपने में डालने में कोई बुराई है मामला-लेकिन क्योंकि स्क्रिप्ट और कार्यक्रमों सब हम शुरू में विश्वास करते हैं कि वे क्या होगा परे जीवन है मैं इसके खिलाफ सलाह देते हैं।


29
envस्थान के बारे में क्या ? POSIX इसे बाध्य नहीं करता है।
जूलियो गुएरा

1
@JulioGuerra मेल को प्रोसेस करने के लिए उपलब्ध /usr/lib/sendmail(या, अभी हाल ही में /usr/sbin/sendmail) बाइनरी को बहुत पसंद करते हैं , यह यूनिक्स की तरह सिस्टम के सर्वोत्तम हित के लिए है /usr/bin/envक्योंकि env shebang ऐसी सामान्य प्रथा है। यह एक वास्तविक मानक इंटरफ़ेस है।
14

8
@ ज़िग्ग इतना यूएन * एक्स है ... <-: मेरा मतलब है, यह उनके लिए सबसे अच्छा हित है एक मानक स्थान के लिए env, लेकिन किसी भी तरह के लिए एक मानक स्थान (जो सिर्फ एक नरम लिंक हो सकता है) नहीं है bash। उल्लेख नहीं है, तो क्यों हैशबैंग सिर्फ स्वीकार नहीं करता है #!bash, और PATHहम इसके साथ बिल्कुल वैसा ही कर रहे हैं, इसके बजाय का उपयोग करें env। बदमाशों के लिए पर्याप्त भ्रमित नहीं है, मुझे लगता है।
ddekany

1
@ जूलियुगरा विकिपीडिया के अनुसार आप सच्चे हैं: यह "गारंटी" नहीं है। इसके बजाय, यह "अधिक संभावित" लगता है। विकिपीडिया This mostly works because the path /usr/bin/env is commonly used for the env utilityयहाँ en.wikipedia.org/wiki/Shebang_(Unix) कहता है - हमें envसभी प्रणालियों में "संभवतः" होने में विश्वास करना चाहिए ।
ज़ावी मोंटेरो

2
@XaviMontero: मैंने एक ऐसी प्रणाली का उपयोग किया है जो अंदर envथी /bin, न कि /usr/bin(जो निश्चित है कि सनोस 4)। इन दिनों यह बहुत संभावना है /usr/bin/envकि सिर्फ #!/usr/bin/envहैक की लोकप्रियता के कारण उपलब्ध होगा ।
कीथ थॉम्पसन

39

बैश का मानक स्थान है /bin, और मुझे संदेह है कि यह सभी प्रणालियों पर सच है। हालांकि, अगर आपको बैश का वह संस्करण पसंद नहीं है तो क्या होगा? उदाहरण के लिए, मैं बैश 4.2 का उपयोग करना चाहता हूं, लेकिन मेरे मैक पर बैश 3.2.5 है।

मैं बैश को फिर से स्थापित करने की कोशिश कर सकता हूं /binलेकिन यह एक बुरा विचार हो सकता है। यदि मैं अपना OS अपडेट करता हूं, तो इसे ओवरराइट कर दिया जाएगा।

हालाँकि, मैं /usr/local/bin/bashअपने पीएटीएच में बैश को स्थापित कर सकता हूं:

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

अब, यदि मैं निर्दिष्ट करता हूं, तो मुझे bashपुराना क्रूड्डी एक नहीं मिलता है /bin/bash, लेकिन नया, शिनियर एक पर /usr/local/bin। अच्छा!

सिवाय मेरी शेल स्क्रिप्ट के कि !# /bin/bashशेबंग है। इस प्रकार, जब मैं अपनी शेल स्क्रिप्ट चलाता हूं, तो मुझे बैश का वह पुराना और घटिया वर्जन मिलता है, जिसमें सहयोगी ऐरे भी नहीं होते हैं।

उपयोग /usr/bin/env bashकरने से मेरे PATH में पाए जाने वाले बैश के संस्करण का उपयोग होगा। यदि मैं अपना PATH सेटअप करता हूं, तो /usr/local/bin/bashइसे निष्पादित किया जाता है, यही वह बैश है जिसका मेरी स्क्रिप्ट उपयोग करेगी।

यह बैश के साथ देखने के लिए दुर्लभ है, लेकिन यह पर्ल और पायथन के साथ बहुत अधिक सामान्य है:

  • कुछ यूनिक्स / लिनक्स रिलीज़ जो स्थिरता पर ध्यान केंद्रित करते हैं, कभी-कभी इन दो स्क्रिप्टिंग भाषाओं की रिलीज़ के पीछे होते हैं। बहुत पहले नहीं, आरएचईएल का पर्ल 5.8.8 पर था - पर्ल का आठ साल पुराना संस्करण! यदि कोई अधिक आधुनिक सुविधाओं का उपयोग करना चाहता था, तो आपको अपना संस्करण स्थापित करना होगा।
  • पर्लब्रेव और पाइथॉनब्रे जैसे कार्यक्रम आपको इन भाषाओं के कई संस्करण स्थापित करने की अनुमति देते हैं। वे उन लिपियों पर निर्भर करते हैं, जो आपके इच्छित संस्करण को प्राप्त करने के लिए आपके PATH में हेरफेर करती हैं। पथ को हार्ड कोड करने का मतलब है कि मैं अपनी स्क्रिप्ट को शराब के नीचे नहीं चला सकता ।
  • यह बहुत पहले नहीं था (ठीक है, यह बहुत पहले था) कि पर्ल और पायथन ज्यादातर यूनिक्स सिस्टम में शामिल मानक पैकेज नहीं थे। इसका मतलब है कि आपको नहीं पता था कि ये दो कार्यक्रम कहां स्थापित किए गए थे। के तहत था /bin? /usr/bin? /opt/bin? कौन जानता है? उपयोग करने का #! /usr/bin/env perlमतलब मुझे पता नहीं था।

और अब आपको क्यों नहीं इस्तेमाल करना चाहिए #! /usr/bin/env bash

जब रास्ता शेबंग में हार्डकोड किया जाता है, तो मुझे उस दुभाषिया के साथ चलना होगा। इस प्रकार, #! /bin/bashमुझे बैश के डिफ़ॉल्ट इंस्टॉल किए गए संस्करण का उपयोग करने के लिए मजबूर करता है। चूँकि बैश फीचर्स बहुत स्टेबल होते हैं (पायथन 3.x के तहत पायथन स्क्रिप्ट का 2.x वर्जन चलाने की कोशिश करें) इसकी बहुत संभावना नहीं है कि मेरी विशेष BASH स्क्रिप्ट काम नहीं करेगी, और चूँकि मेरी bash स्क्रिप्ट शायद इस सिस्टम और अन्य प्रणालियों द्वारा उपयोग की जाती है , बैश के एक गैर-मानक संस्करण का उपयोग करने से अवांछित प्रभाव हो सकते हैं। यह बहुत संभव है कि मैं यह सुनिश्चित करना चाहता हूं कि मेरे शेल स्क्रिप्ट के साथ बैश के स्थिर मानक संस्करण का उपयोग किया जाए। इस प्रकार, मैं शायद अपने शेलबैंग में पथ को कठिन बनाना चाहता हूं।


5
यह सच नहीं है: "बैश का मानक स्थान / बिन है," (जब तक आप एक मानक दस्तावेज़ का हवाला नहीं दे सकते हैं) यह संभवतः अधिक सटीक है कि यह सबसे लिनक्स वितरण और मैकोस पर "सामान्य" स्थान है, लेकिन यह एक नहीं है सामान्य रूप से यूनिक्स सिस्टम पर मानक (और अधिकतर * bsds पर स्थान नहीं है)।
tesch1

13

आह्वान के लिए bashयह थोड़ा अधिक ओवरकिल है। जब तक आपके पास bashअपनी तरह के कई बायनेरिज़ नहीं हैं ~ / bin लेकिन इसका मतलब यह भी है कि आपका कोड $ PATH पर निर्भर करता है कि उसमें सही चीजें हैं।

pythonहालांकि यह चीजों के लिए उपयोगी है । रैपर स्क्रिप्ट और वातावरण हैं जो वैकल्पिक pythonबायनेरिज़ का उपयोग करते हैं।

लेकिन बाइनरी के लिए सटीक पथ का उपयोग करके कुछ भी नहीं खोया जाता है जब तक आप सुनिश्चित हैं कि यह द्विआधारी है जिसे आप वास्तव में चाहते हैं।


के लिए हाजिर python। मैंने स्थानों की संख्या की गिनती खो दी है python
z

2
सहमत है कि /usr/bin/envपायथन के लिए अधिक उपयोगी है, खासकर यदि आप virtualenv का उपयोग करते हैं।
डेनिस

10

ऐसे बहुत सारे सिस्टम हैं जिनमें /binबस कुछ ही नाम रखने के लिए Bash in , FreeBSD और OpenBSD नहीं हैं । यदि आपकी स्क्रिप्ट कई अलग-अलग यूनियनों के पोर्टेबल होने का मतलब है, तो आप #!/usr/bin/env bashइसके बजाय उपयोग करना चाह सकते हैं #!/bin/bash

ध्यान दें कि यह सच नहीं है sh; बॉर्न-कंप्लेंट स्क्रिप्ट के लिए मैं विशेष रूप से उपयोग करता हूं #!/bin/sh, क्योंकि मुझे लगता है कि अस्तित्व में हर यूनिक्स बहुत ज्यादा shहै /bin


उबंटू में 18.04 /binडीर, मैं देखता हूं sh -> dashdashउबंटू के डेबियन प्रकृति को प्रकट करते हुए, प्रतीकात्मक रूप से जुड़ा हुआ है। इन तीन आदेश तार भागो साकार करने के लिए यह सब व्यक्तिगत वरीयता करने पर निर्भर करता: which bashतो which shफिर which dash
noobninja

0

मैं मुख्य स्क्रिप्ट को स्क्रिप्ट में लपेटना पसंद करूंगा जैसे bashकि सिस्टम पर उपलब्ध सभी को जांचने के लिए । इसके उपयोग वाले संस्करण पर अधिक नियंत्रण रखना बेहतर है।

#! /usr/bin/env bash

# This script just chooses the appropriate bash
# installed in system and executes testcode.main

readonly DESIRED_VERSION="5"

declare all_bash_installed_on_this_system
declare bash

if [ "${BASH_VERSINFO}" -ne "${DESIRED_VERSION}" ]
then
    found=0

    all_bash_installed_on_this_system="$(\
        awk -F'/' '$NF == "bash"{print}' "/etc/shells"\
        )"

    for bash in $all_bash_installed_on_this_system
    do
        versinfo="$( $bash -c 'echo ${BASH_VERSINFO}' )"
        [ "${versinfo}" -eq "${DESIRED_VERSION}" ] && { found=1 ; break;}
    done
    if [ "${found}" -ne 1 ]
    then
        echo "${DESIRED_VERSION} not available"
        exit 1
    fi
fi

$bash main_program "$@"

0
 #!/usr/bin/env bash

निश्चित रूप से बेहतर है क्योंकि यह आपके सिस्टम वातावरण चर से बैश निष्पादन योग्य मार्ग को पाता है।

अपने लिनक्स शेल पर जाएं और टाइप करें

env

यह आपके सभी पर्यावरण चर को प्रिंट करेगा।

अपनी शेल स्क्रिप्ट पर जाएं और टाइप करें

echo $BASH

यह आपके बैश पथ (पर्यावरण चर सूची के अनुसार) को प्रिंट करेगा जिसे आपको अपनी स्क्रिप्ट में अपना सही शेबंग पथ बनाने के लिए उपयोग करना चाहिए।

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