शेल-स्क्रिप्ट हेडर (#! / bin / sh vs #! / bin / csh)


92

क्यों सभी स्क्रिप्ट फ़ाइलों के साथ शुरू करते हैं

#!/bin/sh

या के साथ

#!/bin/csh

क्या यह आवश्यक है? इसका उद्देश्य क्या है? और दोनों में क्या अंतर है?


1
एक csh स्क्रिप्ट के लिए, आपको उपयोग करना चाहिए #!/bin/csh -f; -fस्रोत के लिए नहीं खोल बताता उपयोगकर्ता की .loginऔर .cshrcहै, जो स्क्रिप्ट रन तेजी से बनाता है और उपयोगकर्ता के सेटअप के निर्भरता से बचा जाता है। (या बेहतर अभी तक, csh स्क्रिप्ट न लिखें।) -fsh या bash स्क्रिप्ट के लिए उपयोग न करें ; इसका एक ही अर्थ नहीं है।
कीथ थॉम्पसन

जवाबों:


99

यह एक के रूप में जाना जाता है Shebang:

http://en.wikipedia.org/wiki/Shebang_(Unix)

#! दुभाषिया [वैकल्पिक- arg]

शेबबैंग केवल तभी प्रासंगिक होता है जब किसी स्क्रिप्ट में निष्पादन की अनुमति हो (जैसे chmod u + x script.sh)।

जब कोई शेल स्क्रिप्ट निष्पादित करता है तो यह निर्दिष्ट दुभाषिया का उपयोग करेगा।

उदाहरण:

#!/bin/bash
# file: foo.sh
echo 1

$ chmod u+x foo.sh
$ ./foo.sh
  1

@ कोलोब कैन्यन की आपको आवश्यकता नहीं है, लेकिन यह कुछ संपादकों को सिंटैक्स हाइलाइटिंग के साथ मदद कर सकता है (हालांकि आमतौर पर एक ही चीज़ को प्राप्त करने के अन्य तरीके हैं): unix.stackexchange.com/a/88730/193985
ब्रह्म स्नाइडर

42

#!लाइन गिरी (विशेष रूप से, के कार्यान्वयन बताता execveसिस्टम कॉल) है कि यह कार्यक्रम एक व्याख्या की भाषा में लिखा गया है; निरपेक्ष पथनाम जो दुभाषिया की पहचान करता है। मशीन कोड के लिए संकलित कार्यक्रम एक अलग बाइट अनुक्रम के साथ शुरू होते हैं - अधिकांश आधुनिक यूनिक्स पर, 7f 45 4c 46( ^?ELF) जो उन्हें इस तरह से पहचानता है।

जब तक आप उस कार्यक्रम को स्क्रिप्ट नहीं मान लेते#! , तब तक आप जिस भी प्रोग्राम को चाहते हैं, उसके लिए एक पूर्ण मार्ग डाल सकते हैं #!। कर्नेल के एक आह्वान को फिर से लिखता है

./script arg1 arg2 arg3 ...

जहां से ./scriptशुरू होता है, कहते हैं, #! /usr/bin/perlजैसे कि कमांड लाइन वास्तव में थी

/usr/bin/perl ./script arg1 arg2 arg3

या, जैसा कि आपने देखा है, आप #! /bin/shव्याख्या करने के उद्देश्य से एक स्क्रिप्ट लिखने के लिए उपयोग कर सकते हैं sh

#!लाइन केवल यदि आप संसाधित किया जाता है सीधे (स्क्रिप्ट आह्वान ./scriptकमांड लाइन पर); फ़ाइल भी निष्पादन योग्य ( chmod +x script) होनी चाहिए । यदि आप करते हैं sh ./scriptतो #!लाइन आवश्यक नहीं है (और यदि मौजूद है तो इसे नजरअंदाज कर दिया जाएगा), और फ़ाइल को निष्पादन योग्य नहीं होना चाहिए। बिंदु (Do सुविधा का आप को पता है कोई भी भाषा में लिखे गए हैं बिना व्याख्या की भाषा के कार्यक्रमों आह्वान सीधे करने के लिए अनुमति देने के लिए है। grep '^#!' /usr/bin/*- आपको लगता है कि एक महान कई शेयर कार्यक्रमों इस सुविधा का उपयोग वास्तव में कर रहे हैं पता चल जाएगा।)

इस सुविधा का उपयोग करने के लिए यहां कुछ नियम दिए गए हैं:

  • #!बहुत पहले दो होना चाहिए बाइट फ़ाइल में। विशेष रूप से, फ़ाइल को ASCII- संगत एन्कोडिंग में होना चाहिए (जैसे UTF-8 काम करेगा, लेकिन UTF-16 नहीं करेगा) और "बाइट ऑर्डर मार्क" से शुरू नहीं होना चाहिए , या कर्नेल इसे पहचान नहीं पाएगा #!स्क्रिप्ट।
  • के बाद पथ #!एक पूर्ण पथ होना चाहिए (के साथ शुरू होता है /)। इसमें स्थान, टैब या न्यूलाइन वर्ण नहीं हो सकते।
  • यह अच्छी शैली है, लेकिन आवश्यकता नहीं है, #!और के बीच एक स्थान रखना है /। वहां एक से ज्यादा जगह न रखें।
  • आप #!लाइन पर शेल वैरिएबल नहीं डाल सकते हैं , उनका विस्तार नहीं किया जाएगा।
  • निरपेक्ष पथ के बाद आप एक कमांड-लाइन तर्क रख सकते हैं , इसे एक ही स्थान से अलग किया जा सकता है। निरपेक्ष पथ की तरह, इस तर्क में स्थान, टैब या न्यूलाइन वर्ण नहीं हो सकते। कभी-कभी यह काम करने के लिए आवश्यक है ( #! /usr/bin/awk -f), कभी-कभी यह सिर्फ उपयोगी होता है ( #! /usr/bin/perl -Tw)। दुर्भाग्य से, आप निरपेक्ष पथ के बाद दो या अधिक तर्क नहीं रख सकते ।
  • कुछ लोग आपको #! /usr/bin/env interpreterइसके बजाय उपयोग करने के लिए कहेंगे #! /absolute/path/to/interpreterयह लगभग हमेशा एक गलती है। यह आपके प्रोग्राम के व्यवहार $PATHको स्क्रिप्ट के उपयोगकर्ता के चर पर निर्भर करता है। और सभी प्रणालियों envमें पहली जगह नहीं है।
  • ऐसे प्रोग्राम जिनकी आवश्यकता setuidया setgidविशेषाधिकार का उपयोग नहीं किया जा सकता है #!; उन्हें मशीन कोड में संकलित किया जाना है। (यदि आप नहीं जानते कि क्या setuidहै, तो इस बारे में चिंता न करें।)

इस संबंध में csh, यह shमोटे तौर पर संबंधित है जैसा कि न्यूट्रीमैट एडवांस्ड टी सब्सट्रेट चाय के लिए करता है। इंटरएक्टिव उपयोग के लिए इसके shकई फायदे हैं (या बल्कि आधुनिक क्रियान्वयन ने इसे पकड़ लिया है) sh, लेकिन tcshस्क्रिप्टिंग के लिए इसका (या इसके वंशज ) उपयोग करना लगभग हमेशा एक गलती है । यदि आप सामान्य रूप से शेल स्क्रिप्टिंग के लिए नए हैं, तो मैं दृढ़ता से आपको इसे अनदेखा करने और ध्यान केंद्रित करने की सलाह देता हूं sh। यदि आप एक प्रयोग कर रहे हैं cshअपना लॉगिन शेल के रूप में रिश्तेदार, करने के लिए स्विच bashया zsh, ताकि इंटरैक्टिव कमांड भाषा पटकथा आप कर रहे हैं सीखने की भाषा के रूप में ही किया जाएगा।


लिनक्स के हाल के संस्करण निर्दिष्ट दुभाषिया को एक स्क्रिप्ट बनाने की अनुमति देते हैं। के बाद अंतरिक्ष को छोड़ना आम बात है #!; कोई टिप्पणी नहीं कि क्या यह अच्छी शैली है। इस सवाल और हैक के पेशेवरों और विपक्षों की चर्चा के लिए मेरा जवाब देखें #!/usr/bin/env
कीथ थॉम्पसन

@KeithThompson मैं इस धारणा के तहत हूं कि लिनक्स एकमात्र सामान्य यूनिक्स संस्करण है जो दुभाषिया को एक स्क्रिप्ट बनाने की अनुमति देता है, इसलिए यह अभी भी भरोसा करने के लिए कुछ नहीं है। जब से मैंने यह लिखा है मैंने खुद एक ऐसी स्थिति का सामना किया है जहां #!/usr/bin/envराइट थिंग था, लेकिन यह मेरी राय है कि यह लगभग हमेशा एक बुरा विचार है।
zwol

4

यह परिभाषित करता है कि आप अपनी स्क्रिप्ट की व्याख्या / चलाने के लिए किस शेल (कमांड दुभाषिया) का उपयोग कर रहे हैं। प्रत्येक शेल उपयोगकर्ता के साथ इंटरैक्ट करने के तरीके और स्क्रिप्ट्स (प्रोग्राम्स) को निष्पादित करने के तरीके में थोड़ा भिन्न होता है।

जब आप यूनिक्स प्रॉम्प्ट पर एक कमांड टाइप करते हैं, तो आप शेल के साथ इंटरैक्ट कर रहे हैं।

जैसे, #!/bin/cshसी-शेल, /bin/tcshटी-शेल, /bin/bashबैश शेल आदि को संदर्भित करता है ।

आप बता सकते हैं कि आप किस इंटरएक्टिव शेल का उपयोग कर रहे हैं

 echo $SHELL

आदेश, या वैकल्पिक रूप से

 env | grep -i shell

आप कमांड के साथ अपने कमांड शेल को बदल सकते हैं chsh

प्रत्येक के पास थोड़ा अलग कमांड सेट है और वेरिएबल्स को असाइन करने का तरीका और प्रोग्रामिंग कंस्ट्रक्ट्स का अपना सेट है। उदाहरण के लिए यदि बैश के साथ इफ-स्टेटमेंट अलग दिखता है जो कि सी-शेल में है।

यह पृष्ठ ब्याज के रूप में हो सकता है क्योंकि यह बैश और tcsh कमांड / सिंटैक्स के बीच "अनुवाद" करता है।

शेल स्क्रिप्ट में निर्देश का उपयोग करना आपको एक अलग शेल का उपयोग करके प्रोग्राम चलाने की अनुमति देता है। उदाहरण के लिए, मैं tcshशेल को अंतःक्रियात्मक रूप से उपयोग करता हूं , लेकिन अक्सर स्क्रिप्ट फ़ाइल में / बिन / बैश का उपयोग करके बैश स्क्रिप्ट चलाता है।

एक तरफ:

यह अवधारणा अन्य लिपियों तक भी फैली हुई है। उदाहरण के लिए यदि आप पायथन में प्रोग्राम करेंगे तो आप डाल देंगे

 #!/usr/bin/python

अपने पायथन कार्यक्रम के शीर्ष पर


तो क्या यह आवश्यक है? मुझे कैसे पता चलेगा कि मैं वास्तव में किस शेल का उपयोग कर रहा हूं?
एक दो तीन

इसलिए अगर मैं किसी को अपनी मशीन पर उपयोग करने के लिए स्क्रिप्ट लिख रहा हूं, और मुझे नहीं पता कि वे किस शेल का उपयोग कर रहे हैं। (यह व्यक्ति, दुर्भाग्य से, इस सामान के बारे में स्पष्ट है, इस प्रकार वह जो कर सकता है वह है बिना किसी चीज को बदले स्क्रिप्ट को चलाना)। क्या मैं ऐसा कुछ कर सकता हूं #! $SHELL? क्या यह शेबंग में सही खोल डाल देगा?
एक दो तीन

1
@OneTwoThree अधिकांश सिस्टम में मानक गोले हैं, यदि आप एक बैश या csh स्क्रिप्ट लिखते हैं तो आप ठीक रहेंगे। वे किस शैल का उपयोग अंतःक्रियात्मक रूप से कर रहे हैं , इससे कोई फर्क नहीं पड़ता, उदाहरण के लिए, !#/bin/bashनिर्देशन की सुंदरता है । यह सिस्टम को बताता है कि आपके शेल स्क्रिप्ट को निष्पादित करने के लिए किस शेल का उपयोग करना है।
लेवोन

का मूल्य $SHELLजरूरी है कि कौन सा शैल आप इस समय चल रहे हैं बता नहीं करता है; यह सामान्य रूप से आपको आपका डिफ़ॉल्ट शेल बताता है । tcsh सेट $versionऔर $tcsh; बैश सेट $BASH_VERSION। जरूरी नहीं कि सभी गोले एक जैसे ही हों।
कीथ थॉम्पसन

1
@OneTwoThree: #!लाइन को स्क्रिप्ट के सिंटैक्स से मेल खाना है, कि जो कोई भी स्क्रिप्ट चला रहा है उसका इस्तेमाल किया गया इंटरेक्टिव शेल।
कीथ थॉम्पसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.