मुझे कब उपयोग करना चाहिए #? / Bin / bash और कब #? / Bin / sh?


104

शेल स्क्रिप्ट की #!/bin/bashतुलना #!/bin/shमें अधिक उपयुक्त कब है ?


55
जब आप bashफ़ंक्शन और सिंटैक्स के बजाय फ़ंक्शन और सिंटैक्स का उपयोग कर रहे हैं sh
Mokubai


3
यदि यह किसी की मदद करता है, तो मैंने देखा है कि यदि आपकी स्क्रिप्ट में शेबंग है तो vimयह प्रकाश डाला जाएगा । मैं केवल इसे बदल देता हूं अगर चीजों को बालों की जरूरत होती है ताकि उन्हें बैश-फीचर्स की जरूरत हो। bash#!/bin/shbash
सेलडोमनैडी

@SeldomNeedy कुछ चीजों को डिफ़ॉल्ट रूप से हाइलाइट करता है जो किसी भी POSIX शेल में ठीक काम करते हैं। $(...)विशेष रूप से अप्रिय है। इसके अलावा, उनमें से कुछ सूक्ष्म हैं [ <(...)और cmd >& fileकोई भी हाइलाइटिंग त्रुटि नहीं मिलती है, उदाहरण के लिए, उनके पास विशेष हाइलाइटिंग नहीं है कि वे क्या मतलब है, साथ या बिना g:is_bash]
Random832

@ Random832 लगता है कि हाल ही में विम के इश्यू-ट्रैकर में इस विषय पर कुछ गतिविधि हुई है ।
सेलडोमनेडी

जवाबों:


150

संक्षेप में:

  • कई गोले हैं जो पोसिक्स श विनिर्देश के सुपरसेट को लागू करते हैं । अलग-अलग सिस्टम पर, /bin/shऐश, बैश, डैश, ksh, zsh, और c का लिंक हो सकता है। (यह हमेशा श-संगत होगा - कभी भी csh या fish नहीं।)

  • जब तक आप shकेवल सुविधाओं से चिपके रहते हैं , तब तक आप (और शायद यहां तक ​​कि) का उपयोग कर सकते हैं #!/bin/shऔर स्क्रिप्ट को ठीक काम करना चाहिए, चाहे वह कोई भी शेल हो।

  • यदि आप बैश-विशिष्ट सुविधाओं (जैसे सरणियों) का उपयोग करना शुरू करते हैं, तो आपको विशेष रूप से बैश का अनुरोध करना चाहिए - क्योंकि, भले ही /bin/shपहले से ही आपके सिस्टम पर बैश का आह्वान करता हो, यह हर किसी के सिस्टम पर नहीं हो सकता है, और आपकी स्क्रिप्ट वहां नहीं चलेगी। (पाठ्यक्रम का यही तरीका zsh और ksh पर भी लागू होता है।) आप बशेकिट की पहचान करने के लिए शेलचेक का उपयोग कर सकते हैं ।

  • भले ही स्क्रिप्ट केवल व्यक्तिगत उपयोग के लिए हो, आप यह देख सकते हैं /bin/shकि उन्नयन के दौरान कुछ OS बदल जाते हैं - उदाहरण के लिए डेबियन पर यह बैश हुआ करता था, लेकिन बाद में इसे बहुत कम डैश के साथ बदल दिया गया। लिपियों में बशीरों का उपयोग किया गया था लेकिन #!/bin/shअचानक टूट गया था।

हालाँकि:

  • यहां तक ​​कि #!/bin/bashबहुत सही नहीं है। अलग सिस्टम पर, पार्टी में रहते हो सकता है /usr/binया /usr/pkg/binया /usr/local/bin

  • एक अधिक विश्वसनीय विकल्प है #!/usr/bin/env bash, जो $ PATH का उपयोग करता है। (हालांकि envउपकरण स्वयं को या तो सख्ती से गारंटी नहीं देता है, फिर /usr/bin/envभी अधिक सिस्टम पर काम /bin/bashकरता है।)


10
अच्छा जवाब। क्या आपको इसे सीडब्ल्यू बनाने का मतलब था?
Mokubai

3
बस एक टिप्पणी यदि बैश से चलाया जाता है /bin/shतो यह shसुविधाओं ( मैन पेज देखें ) की नकल करने की कोशिश करेगा , निश्चित नहीं कि बैश विशिष्ट सुविधाएँ इस मोड में उपलब्ध हैं। envटूल एक पॉज़िक्स टूल है जिसे अधिकांश वितरण में पाया जाना चाहिए, लेकिन मैं अनिश्चित हूं क्योंकि कुछ पॉज़िक्स का सम्मान नहीं कर सकते हैं।
ब्राइस

8
नहीं, वास्तव में POSIX विशेष रूप से बताता है कि इसमें ऐसा नहीं माना जा सकता है /bin: " अनुप्रयोगों को ध्यान में रखना चाहिए कि शेल के लिए मानक PATH को / बिन / श / या usr / बिन / श होना नहीं माना जा सकता है, और इसे निर्धारित किया जाना चाहिए। PATH द्वारा पूछताछ getconf PATH द्वारा लौटाए जाने से, यह सुनिश्चित करते हुए कि लौटाया गया पथनाम एक पूर्ण पथनाम है न कि एक शेल-इन "। इस प्रश्न को भी देखें और विशेष रूप से इस उत्तर को
टेराडो

12
हम्म, ठीक है, तो इसका मतलब है कि POSIX वास्तव में #!स्क्रिप्ट काम करने के लिए एक पोर्टेबल तरीका परिभाषित नहीं करता है ?
grawity

4
पोसिक्स श बोर्न नहीं है : यह शुरुआती क्ष की तुलना में अधिक व्युत्पन्न है, क्योंकि यह बोर्न का प्रत्यक्ष वंशज है। उन्हें भेद करना आसान है: पोसिक्स श में echo foo ^ catउत्सर्जन करता foo ^ catहै, और केवल fooबॉर्न में उत्सर्जन करता है (जैसा ^कि वहां एक पाइप चरित्र है)।
चार्ल्स डफी

18

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

इस पर विचार करें: यदि आप छोड़ देते हैं #!/bin/bashऔर आपके उपयोगकर्ताओं के पास नहीं है, तो उन्हें एक स्पष्ट त्रुटि संदेश दिखाई देगा, कुछ ऐसा

Error: /bin/bash not found

अधिकांश उपयोगकर्ता उपयुक्त पैकेज को स्थापित करके इसे एक मिनट के भीतर ठीक कर सकते हैं। दूसरी ओर, यदि आप शेबबैंग को बदलते हैं #!/bin/shऔर इसे एक ऐसे सिस्टम पर टेस्ट करते हैं, जहां /bin/shएक सिमलिंक है /bin/bash, तो आपके उपयोगकर्ताओं bashको परेशानी नहीं होगी। वे सबसे अधिक संभावित रूप से एक गुप्त त्रुटि संदेश देखेंगे:

Error in script.sh line 123: error parsing token xyz

इसे ठीक करने में घंटों लग सकते हैं, और इस बात का कोई सुराग नहीं होगा कि उन्हें किस शेल का उपयोग करना चाहिए था।

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


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

1
रहने भी दो। मैंने इस भाग को गलत समझा "आप का उपयोग क्यों करना चाहते हैं" ...
हास्तूर

6

आपको केवल कभी उपयोग करना चाहिए #! /bin/sh

आपको शेल स्क्रिप्ट में कभी भी बैश (या zsh, या फिश, या ...) एक्सटेंशन का उपयोग नहीं करना चाहिए।

आपको केवल शेल स्क्रिप्ट लिखना चाहिए जो शेल भाषा के किसी भी कार्यान्वयन के साथ काम करती है (सभी "उपयोगिता" प्रोग्राम जो शेल के साथ ही जाते हैं)। इन दिनों आप संभवतः POSIX.1-2001 ( not -2008) को शेल और उपयोगिताओं में सक्षम होने के लिए आधिकारिक के रूप में ले सकते हैं, लेकिन इस बात से अवगत रहें कि हो सकता है कि आप एक दिन अपनी लिपि को एक विरासत प्रणाली (जैसे Solaris) में पोर्ट कर सकें। या एआईएक्स) जिसका खोल और उपयोगिताओं को लगभग 1992 में जमे हुए किया गया था।

क्या, गंभीरता से ?!

हां गंभीरतापूर्वक।

यहाँ बात है: शैल एक भयानक प्रोग्रामिंग भाषा है। इसके लिए केवल एक चीज है जो यह है कि /bin/shएक और केवल स्क्रिप्ट दुभाषिया है जो हर यूनिक्स इंस्टॉलेशन की गारंटी है।

यहाँ दूसरी बात है: कोर पर्ल 5 इंटरप्रेटर ( /usr/bin/perl) की कुछ पुनरावृति अधिक संभावना है कि यह बेतरतीब ढंग से चयनित यूनिक्स इंस्टॉलेशन पर उपलब्ध (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bashहै। अन्य अच्छी स्क्रिप्टिंग लैंग्वेज (पायथन, रूबी, नोड.जेएस, इत्यादि - मैं PHP और Tcl को उस श्रेणी में भी शामिल करूँगा जब शेल की तुलना) भी लगभग बैश और अन्य विस्तारित शेल के रूप में उपलब्ध है।

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

अब, सरल शेल स्क्रिप्ट, जिस तरह से क्रोन जॉब या किसी चीज़ के अनुक्रम में कुछ प्रोग्राम चलाए जाते हैं, उन्हें शेल स्क्रिप्ट के रूप में छोड़ने में कुछ भी गलत नहीं है। लेकिन सरल शेल स्क्रिप्ट में सरणियों या कार्यों या [[यहां तक ​​कि आवश्यकता नहीं है । और आपको केवल जटिल शेल स्क्रिप्ट लिखना चाहिए जब आपके पास कोई अन्य विकल्प नहीं हो। उदाहरण के लिए, ऑटोकॉन्फ़ स्क्रिप्ट, अभी भी शैल स्क्रिप्ट ठीक से हैं। लेकिन उन लिपियों को हर/bin/sh उस अवतार पर चलाना पड़ता है जो प्रोग्राम के कॉन्फिगर होने के लिए प्रासंगिक है। और इसका मतलब है कि वे किसी भी एक्सटेंशन का उपयोग नहीं कर सकते हैं। आपको शायद इन दिनों पुराने स्वामित्व वाले यूनिक्स के बारे में परवाह करने की ज़रूरत नहीं है, लेकिन आपको शायद वर्तमान ओपन-सोर्स बीएसडी के बारे में परवाह करनी चाहिए , जिनमें से कुछ स्थापित नहीं हैंbashडिफ़ॉल्ट रूप से, और एम्बेडेड वातावरण जो आपको केवल एक न्यूनतम शेल देते हैं और busybox

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


4
क्षमा करें, लेकिन यह थोड़ा मूर्खतापूर्ण है। हां, यदि आप कुछ ऐसा लिख ​​रहे हैं जो i) वितरित और ii) अलग-अलग वातावरण में है, तो आपको मूल से चिपके रहना चाहिए sh। हालांकि, यह बताते हुए कि आप अन्य गोले का उपयोग कभी नहीं करना चाहिए, से बहुत दूर है । हर दिन हजारों (शायद कई और) स्क्रिप्ट लिखी जाती हैं और उनमें से अधिकांश केवल एक मशीन पर चलेंगी। आपकी सलाह उत्पादन कोड पर समझ में आता है, लेकिन दैनिक "sysdaminy" नौकरियों के लिए नहीं जो अधिकांश स्क्रिप्ट के लिए लिखे गए हैं। अगर मुझे पता है कि मेरी स्क्रिप्ट केवल मेरे द्वारा और लिनक्स मशीन पर इस्तेमाल की जाएगी, तो बैश ठीक है।
टेराडॉन

1
@terdon बिंदु यह है कि यदि आपके पास बैश स्क्रिप्ट लिखने का विकल्प है, तो आपके पास एक पर्ल (या जो भी) स्क्रिप्ट लिखने का विकल्प है, और यह हमेशा बेहतर विकल्प है।
zwol

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

@ ThorstenSchöning मैंने थोड़ा मूर्खतापूर्ण कहा । अगर यह यूनिक्स और लिनक्स या यहां तक ​​कि स्टैक ओवरफ्लो थे, तो मैं भी सहमत हो सकता हूं। यदि हम सामान्य सर्वोत्तम अभ्यास, या पेशेवर प्रोग्रामर के बारे में बात कर रहे हैं, तो निश्चित रूप से बेसिक POSIX sh से चिपकना सबसे अच्छा है। हालांकि, यह सुपर उपयोगकर्ता है , जो एक साइट है जिसका उद्देश्य अंतिम उपयोगकर्ता हैं और लोगों को बता रहे हैं कि शेल स्क्रिप्ट लिखने के दौरान कभी भी बैश या जेड का उपयोग नहीं करना चाहिए, मेरी राय में, चरम पर।
टेराडन

@terdon यह वास्तव में अधिक महत्वपूर्ण है, मेरी राय में, जटिल शेल स्क्रिप्ट लिखने से उपयोगकर्ताओं को हतोत्साहित करने के लिए। पेशेवरों के पास औसत रूप से उच्च कौशल स्तर होता है (इस प्रकार वे जटिल शेल स्क्रिप्टिंग के नुकसान से निपटने में सक्षम होने की संभावना रखते हैं), कुछ सटीकता के साथ पता होना चाहिए कि उन्हें कौन से वातावरण में पोर्टेबल होने की आवश्यकता है, और भुगतान नहीं करने के लिए भुगतान किया जा रहा है। हताशा में।
zwol

4

आमतौर पर अगर समय कार्यक्षमता से अधिक महत्वपूर्ण है तो आप तेज शेल का उपयोग करेंगे। श को अक्सर डैश के लिए उतारा जाता है और रूट के क्रोन कार्यों या बैच संचालन के लिए उपयोग किया जाता है, जहां हर (नैनो) दूसरा मायने रखता है।


2
फाइलसिस्टम से एक अतिरिक्त शेल दुभाषिया लोड करना इस तरह के एक लाभ को नकार सकता है, और कुछ भी जहां नैनोसैकेड (जो वास्तविक मशीन चक्र के रूप में परिमाण के समान क्रम में हैं) गिनती सी और विधानसभा भाषा प्रोग्रामर का डोमेन है।
रैकैंडबॉमनमैन

यदि आप उनमें से अरबों हैं, तो नैनोसेकंड केवल क्रोन नौकरियों में अंतर करते हैं, और क्रोन वैसे भी इतने सारे को संभालने में सक्षम नहीं होंगे।
दिमित्री ग्रिगोरीव

1
यहां तक ​​कि अगर mckenzm थोड़ा अतिरंजित है, वहाँ कोई इनकार नहीं है कि अधिक प्रदर्शन बेहतर है! "नैनो" भाग पर मत लटकाओ। (नैनोसेकंड सी में तब तक भी नहीं गिना जाता है जब तक कि यह एक वास्तविक समय प्रणाली या इस तरह के एक आंतरिक लूप नहीं है!)
जेपीओ ११'१६

1
@jpaugh जब तक आप एक ऐसी (विरासत) प्रणाली के साथ काम कर रहे हैं, जो यह मानती है कि कुछ परिचालनों में कम से कम एक विशिष्ट समय लगेगा। होता है!
JAB

3

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


1
  • श (अधिकांश मामलों के लिए), यदि विशेष रूप से आवश्यक हो (या ksh, या जो भी हो)

सबसे सुरक्षित रास्ता। जब हार्ड कोडित, होगा / usr / bin / / shellOfChoiceलेकिन एक नया सम्मेलन मैं हमेशा उपयोग करने की कोशिश कर रहा हूं - एक परिवर्तन के माध्यम से 'डिफ़ॉल्ट स्थानों' के रूप में PATH बदल सकता है:

#! / usr / bin / env sh या
#! / usr / bin / env bash
या उदाहरण के लिए, पर्ल स्क्रिप्ट
#! / usr / bin / env perl -w

बेशक, जब आपके पास एक स्क्रिप्ट के लिए कभी भी एक नया PATH लेने का कारण होता है, तो इसे हार्ड-कोडित करना जारी रखें - और फिर / usr / bin / कुछ का उपयोग करने के लिए सबसे अधिक संभावना पथ होना चाहिए।

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