अधिकतम पोर्टेबिलिटी के लिए #! / bin / sh vs #! / bin / bash

cherouvim 07/30/2017. 3 answers, 2.886 views
linux bash shell sh

मैं आमतौर पर उबंटू एलटीएस सर्वर के साथ काम करता हूं जो कि मैं सिम्लिंक /bin/sh /bin/dash को समझता हूं। सिमलिंक /bin/sh /bin/bash बावजूद कई अन्य distros।

उस से मैं समझता हूं कि यदि कोई स्क्रिप्ट शीर्ष पर #!/bin/sh का उपयोग करती है तो यह सभी सर्वरों पर समान तरीके से नहीं चल सकती है?

क्या कोई सुझाव दिया गया है कि स्क्रिप्ट के लिए किस शैल का उपयोग करना है जब कोई सर्वर के बीच उन स्क्रिप्ट्स की अधिकतम पोर्टेबिलिटी चाहता है?

1 Comments
Thorbjørn Ravn Andersen 08/01/2017
विभिन्न गोले के बीच थोड़ा अंतर है। यदि पोर्टेबिलिटी आपके लिए सबसे महत्वपूर्ण है तो #!/bin/sh का उपयोग करें और मूल खोल प्रदान किए गए किसी भी चीज़ का उपयोग न करें।

3 Answers


Gordon Davisson 08/01/2017.

शैल स्क्रिप्ट के लिए पोर्टेबिलिटी के लगभग चार स्तर हैं (जहां तक ​​शेबांग लाइन का संबंध है):

  1. सबसे पोर्टेबल: #!/bin/sh shebang का उपयोग करें और only POSIX मानक में निर्दिष्ट मूल खोल वाक्यविन्यास का उपयोग करें। यह किसी भी POSIX / यूनिक्स / लिनक्स सिस्टम पर बहुत अधिक काम करना चाहिए। (ठीक है, सोलारिस 10 और इससे पहले कि वास्तविक विरासत बोर्न शेल था, जो पॉज़िक्स को इतना अनुपालन करता था, जैसे /bin/sh ।)

  2. दूसरा सबसे पोर्टेबल: #!/bin/bash (या #!/usr/bin/env bash ) शेबैंग लाइन का उपयोग करें, और v3 सुविधाओं को बाश करने के लिए चिपकाएं। यह किसी भी सिस्टम पर काम करेगा जिसमें बैश (अपेक्षित स्थान में) है।

  3. तीसरा सबसे पोर्टेबल: #!/bin/bash (या #!/usr/bin/env bash ) शेबैंग लाइन का उपयोग करें, और बैश v4 सुविधाओं का उपयोग करें। यह किसी भी सिस्टम पर असफल हो जाएगा जिसमें बैश v3 है (उदाहरण के लिए मैकोज़, जिसे लाइसेंस कारणों के लिए उपयोग करना है)।

  4. कम पोर्टेबल: #!/bin/sh shebang का उपयोग करें और पॉज़िक्स खोल वाक्यविन्यास में बैश एक्सटेंशन का उपयोग करें। यह किसी भी सिस्टम पर असफल हो जाएगा जिसमें / bin / sh (जैसे हालिया उबंटू संस्करण) के लिए बैश के अलावा कुछ और है। ऐसा कभी मत करो; यह सिर्फ एक संगतता मुद्दा नहीं है, यह सिर्फ सादा गलत है। दुर्भाग्य से, यह एक त्रुटि है जो बहुत से लोग करते हैं।

मेरी सिफारिश: पहले तीनों के सबसे रूढ़िवादी का उपयोग करें जो आपको स्क्रिप्ट के लिए आवश्यक सभी शैल सुविधाओं की आपूर्ति करता है। अधिकतम पोर्टेबिलिटी के लिए, विकल्प # 1 का उपयोग करें, लेकिन मेरे अनुभव में कुछ बाश विशेषताएं (जैसे सरणी) पर्याप्त सहायक हैं कि मैं # 2 के साथ जाऊंगा।

गलत शेबांग का उपयोग करके आप सबसे बुरी चीज # 4 कर सकते हैं। यदि आप सुनिश्चित नहीं हैं कि कौन सी विशेषताएं मूल POSIX हैं और जो बैश एक्सटेंशन हैं, तो या तो एक बैश शेबैंग (यानी विकल्प # 2) के साथ चिपके रहें, या स्क्रिप्ट का परीक्षण एक बहुत ही बुनियादी शैल (जैसे आपके उबंटू एलटीएस सर्वर पर) के साथ पूरी तरह से करें। उबंटू विकी के लिए देखने के लिए बशिस की एक अच्छी सूची है

यूनिक्स और लिनक्स प्रश्न में शैल के बीच इतिहास और मतभेदों के बारे में कुछ बहुत अच्छी जानकारी है "sh अनुकूल होने का क्या अर्थ है?" और स्टैक ओवरफ्लो प्रश्न "sh और bash के बीच अंतर"

साथ ही, ध्यान रखें कि शैल एकमात्र चीज नहीं है जो विभिन्न प्रणालियों के बीच भिन्न होती है; यदि आप लिनक्स में उपयोग किए जाते हैं, तो आप जीएनयू कमांड के लिए उपयोग किए जाते हैं, जिनमें बहुत से गैर-मानक एक्सटेंशन हैं जो आपको अन्य यूनिक्स सिस्टम (जैसे बीएसडी, मैकोज़) पर नहीं मिल सकते हैं। दुर्भाग्यवश, यहां कोई आसान नियम नहीं है, आपको बस उपयोग किए जा रहे आदेशों के लिए भिन्नता की सीमा जाननी है।

पोर्टेबिलिटी के मामले में सबसे नास्टेस्ट कमांडों में से एक सबसे बुनियादी है: echo । जब भी आप प्रिंट करने के लिए स्ट्रिंग में किसी भी विकल्प (जैसे echo -n या echo -e ), या किसी भी एस्केप (बैकस्लाश) के साथ इसका उपयोग करते हैं, तो अलग-अलग संस्करण अलग-अलग चीजें करेंगे। जब भी आप बिना किसी लाइनफीड के स्ट्रिंग को मुद्रित करना चाहते हैं, या स्ट्रिंग में भागने के साथ, इसके बजाय printf उपयोग करें (और सीखें कि यह कैसे काम करता है - यह echo से अधिक जटिल है)। ps कमांड भी एक गड़बड़ है

कमांड विकल्प सिंटैक्स के लिए हालिया / जीएनयूश एक्सटेंशन के लिए एक और सामान्य चीज़-टू-घड़ी है: पुराने (मानक) कमांड प्रारूप यह है कि कमांड विकल्पों के बाद होता है (एक डैश के साथ, और प्रत्येक विकल्प एक ही अक्षर होता है), उसके बाद आदेश तर्क। हालिया (और अक्सर गैर-पोर्टेबल) वेरिएंट में लंबे विकल्प (आमतौर पर -- साथ पेश किए गए) शामिल होते हैं, तर्कों के बाद आने वाले विकल्पों की अनुमति देते हैं, और तर्कों से विकल्पों को अलग करने के लिए उपयोग करते हैं।

5 comments
12 pabouk 07/30/2017
चौथा विकल्प बस एक गलत विचार है। कृपया इसका इस्तेमाल न करें।
3 Gordon Davisson 07/30/2017
@pabouk मैं पूरी तरह से सहमत हूं, इसलिए मैंने यह स्पष्ट करने के लिए अपना जवाब संपादित किया।
1 jlliagre 07/30/2017
आपका पहला कथन थोड़ा भ्रामक है। POSIX मानक शेबैंग के बारे में कुछ भी निर्दिष्ट नहीं करता है, यह बताते हुए कि यह अनिश्चित व्यवहार की ओर जाता है। इसके अलावा, POSIX निर्दिष्ट नहीं करता है कि पॉज़िक्स खोल कहाँ स्थित होना चाहिए, केवल उसका नाम ( sh ), इसलिए /bin/sh सही पथ होने की गारंटी नहीं है। सबसे पोर्टेबल तब किसी भी शेबैंग को निर्दिष्ट नहीं करना है, या ओएस को शेबैंग को अनुकूलित करने के लिए नहीं है।
2 Michael Kjörling 07/30/2017
मैं हाल ही में अपनी एक स्क्रिप्ट के साथ # 4 में गिर गया, और सिर्फ यह नहीं समझ सका कि यह क्यों काम नहीं कर रहा था; आखिरकार, वही आदेश दृढ़ता से काम करते थे, और वही किया जो मैं चाहता था कि मैं उन्हें करना चाहूंगा, जब मैंने उन्हें सीधे खोल में करने की कोशिश की। जैसे ही मैंने #!/bin/sh को #!/bin/bash बदल दिया, लिपि पूरी तरह से काम किया। (मेरी रक्षा के लिए, उस स्क्रिप्ट को उस समय से विकसित किया गया था, जिसकी वास्तव में केवल शस्त्रों की आवश्यकता होती थी, जो कि बैश जैसी व्यवहार पर निर्भर था।)
2 jlliagre 07/30/2017
@ माइकल Kjörling (सच) बोर्न खोल लगभग लिनक्स वितरण के साथ कभी नहीं बंडल किया गया है और वैसे भी POSIX अनुपालन नहीं है। पॉज़िक्स मानक खोल ksh व्यवहार से बनाया गया था, बोर्न नहीं। एफएचएस डू के बाद सबसे अधिक लिनक्स डिस्ट्रीब्यूशन में पीओएसईक्स संगतता, आमतौर पर bash या dash प्रदान करने के लिए चुने गए खोल के लिए एक प्रतीकात्मक लिंक होने के नाते /bin/sh होता है।

Kaz 07/31/2017.

./configure स्क्रिप्ट में जो इमारत के लिए TXR भाषा तैयार करता है, मैंने बेहतर पोर्टेबिलिटी के लिए निम्न प्रस्ताव लिखा है। स्क्रिप्ट स्वयं बूटस्ट्रैप करेगा, भले ही #!/bin/sh एक गैर-पॉज़िक्स-अनुरूप पुरानी बोर्न शेल है। (मैं सोलारिस 10 वीएम पर हर रिलीज का निर्माण करता हूं)।

#!/bin/sh

# use your own variable name instead of txr_shell;
# adjust to taste: search for your favorite shells

if test x$txr_shell = x ; then
  for shell in /bin/bash /usr/bin/bash /usr/xpg4/bin/sh ; do
    if test -x $shell ; then
       txr_shell=$shell
       break
    fi
  done
  if test x$txr_shell = x ; then
    echo "No known POSIX shell found: falling back on /bin/sh, which may not work"
    txr_shell=/bin/sh
  fi
  export txr_shell
  exec $txr_shell $0 ${@+"$@"}
fi

# rest of the script here, executing in upgraded shell 

यहां विचार यह है कि हम उस व्यक्ति के मुकाबले बेहतर खोल पाते हैं, जिसे हम चल रहे हैं, और उस खोल का उपयोग करके स्क्रिप्ट को फिर से निष्पादित करें। txr_shell पर्यावरण चर सेट किया गया है, ताकि पुन: निष्पादित स्क्रिप्ट को पता txr_shell कि यह पुनः निष्पादित रिकर्सिव उदाहरण है।

(मेरी स्क्रिप्ट में, txr_shell चर का उपयोग बाद में दो उद्देश्यों के लिए किया जाता है: सबसे पहले इसे स्क्रिप्ट के आउटपुट में एक सूचनात्मक संदेश के हिस्से के रूप में मुद्रित किया जाता है। दूसरा, इसे SHELL में SHELL चर के रूप में स्थापित किया जाता है, ताकि व्यंजनों को निष्पादित करने के लिए भी इस खोल का उपयोग करेंगे।)

एक सिस्टम पर जहां /bin/sh डैश है, आप देख सकते हैं कि उपर्युक्त तर्क /bin/bash को मिलेगा और इसके साथ स्क्रिप्ट को फिर से निष्पादित करेगा।

एक सोलारिस 10 बॉक्स पर, यदि कोई बैश नहीं मिलता है तो /usr/xpg4/bin/sh किक होगा।

प्रस्तावना एक रूढ़िवादी खोल बोली में लिखा गया है, फ़ाइल अस्तित्व परीक्षणों के परीक्षण के लिए, और ${@+"$@"} कुछ टूटे हुए पुराने गोले (जो कि "$@" होगा, जो कि "$@" होगा एक पॉज़िक्स अनुरूप शेल में)।

2 comments
Charles Duffy 07/31/2017
यदि उचित उद्धरण उपयोग में था, तो किसी को x हैकरी की आवश्यकता नहीं होगी, क्योंकि ऐसी स्थितियों ने अनिवार्य रूप से आस-पास की स्थिति को बहिष्कृत किया -a या कई परीक्षणों के संयोजन के साथ -a साथ परीक्षण के आविष्कार को भी हटा दिया है।
Kaz 07/31/2017
@ चार्ल्स डफी वास्तव में; test x$whatever मैं कर रहा हूं वह वार्निश में प्याज की तरह दिखता है। अगर हम उद्धृत करने के लिए टूटे हुए पुराने खोल पर भरोसा नहीं कर सकते हैं, तो अंतिम ${@+"$@"} प्रयास व्यर्थ है।

zwol 07/31/2017.

बोर्न शैल भाषा की सभी विविधताएं पर्ल, पायथन, रूबी, नोड.जेएस, और यहां तक ​​कि (तर्कसंगत) टीसीएल जैसी आधुनिक स्क्रिप्टिंग भाषाओं की तुलना में काफी भयानक हैं। यदि आपको कुछ भी जटिल करना है, तो आप लंबे समय तक खुश रहेंगे यदि आप शेल स्क्रिप्ट के बजाय उपरोक्त में से किसी एक का उपयोग करते हैं।

एक और एकमात्र लाभ शैल भाषा अभी भी उन नई भाषाओं में है, यह है कि something खुद को कॉल करने के लिए /bin/sh को यूनिक्स होने के लिए आवश्यक कुछ भी मौजूद है। हालांकि, यह कुछ भी POSIX- अनुपालन नहीं हो सकता है; यूनिक्स 95 (हाँ, यूनिक्स 95, बीस साल पहले और गिनती) द्वारा किए गए परिवर्तनों prior विरासत मालिकाना यूनिक्सों ने कई भाषाओं /bin/sh द्वारा लागू भाषा को डिफ़ॉल्ट पीएटीएच में लागू किया था। यूनिक्स 95, या यहां तक ​​कि POSIX.1-2001 का एक सेट हो सकता है यदि आप भाग्यशाली हैं, निर्देशिका में उपकरण डिफ़ॉल्ट पथ (जैसे /usr/xpg4/bin ) पर नहीं हैं लेकिन वे मौजूद होने की गारंटी नहीं देते हैं।

हालांकि, पर्ल की मूल बातें बैब की तुलना में मनमाने ढंग से चयनित यूनिक्स स्थापना पर मौजूद more likely है। ("पर्ल की मूल बातें" से मेरा मतलब है /usr/bin/perl मौजूद है और some संभवतः पुराना है, पर्ल 5 का संस्करण है, और यदि आप भाग्यशाली हैं तो दुभाषिया के उस संस्करण के साथ भेजे गए मॉड्यूल का सेट भी है उपलब्ध।)

इसलिए:

यदि आप ऐसा कुछ लिख रहे हैं जिसे everywhere काम करना everywhere जो यूनिक्स (जैसे "कॉन्फ़िगर" स्क्रिप्ट) के रूप में प्रस्तुत करता है, तो आपको #! /bin/sh का उपयोग करने की आवश्यकता है #! /bin/sh #! /bin/sh , और आपको किसी भी एक्सटेंशन का उपयोग करने की आवश्यकता नहीं है। आजकल मैं इस परिस्थिति में POSIX.1-2001-compliant shell लिखूंगा, लेकिन अगर कोई जंगली लोहे के लिए समर्थन मांगता है तो मैं POSIXISms को पैच करने के लिए तैयार रहूंगा।

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

(तो बैश एक्सटेंशन का उपयोग करना उचित कब is ? पहले ऑर्डर करने के लिए: कभी नहीं। दूसरे ऑर्डर के लिए: केवल बैश इंटरैक्टिव वातावरण का विस्तार करने के लिए - उदाहरण के लिए स्मार्ट टैब-पूर्णता और फैंसी प्रॉम्प्ट प्रदान करना।)

Related questions

Hot questions

Language

Popular Tags