शेल स्क्रिप्ट लिखना जो किसी भी शेल पर चलेगा (कई शेलंग लाइनों का उपयोग करके?)


19

मैंने अभी-अभी शेल स्क्रिप्टिंग में गहराई से जाना शुरू किया है, और मैंने हमेशा अपनी स्क्रिप्ट को एक फ़ाइल में फेंक दिया है, इसे चिह्नित किया है chmod +xऔर फिर किया है /path/to/script.shऔर जो कुछ भी दुभाषिया है वह डिफ़ॉल्ट है इसके साथ अपना रास्ता है, जिसे मैंने मान लिया था कि यह zsh था क्योंकि यही है मैंने अपने खोल के लिए इस्तेमाल किया। जाहिरा तौर पर ऐसा लगता है कि यह सिर्फ /bin/shडिफ़ॉल्ट रूप से है, भले ही मैं स्क्रिप्ट को एक zsh प्रॉम्प्ट से निष्पादित करता हूं, क्योंकि मैंने अपनी स्क्रिप्ट में zsh-specific सामान डालना शुरू कर दिया है और जब तक मैं नहीं चलता तब तक यह विफल हो रहा है zsh /path/to/script.sh

इस बिंदु पर जाने के लिए, यहाँ मेरे प्रश्न हैं:

  1. जब कोई शेब लाइन ( #!/path/to/shell) शुरुआत में नहीं है, तो कौन सी शेल स्क्रिप्ट निष्पादित करती है ? मुझे लगता है /bin/shलेकिन मैं पुष्टि नहीं कर सकता।
  2. शेल स्क्रिप्ट लिखने के संदर्भ में "सर्वोत्तम प्रथाओं" को क्या माना जाता है जो किसी भी मंच पर चलेगा? (ठीक है, यह ओपन-एंड की तरह है)
  3. क्या यह एक स्क्रिप्ट लिखना संभव है जो zsh का उपयोग करने की कोशिश करता है और अगर zsh उपलब्ध नहीं है तो वापस बश करने के लिए गिर जाता है? मैंने नीचे की तरह दो शबंग रेखाएँ डालने की कोशिश की है, लेकिन bad interpreter: /bin/zsh: no such file or directoryअगर मैं इसे बिना किसी मशीन पर आज़माता हूँ तो यह केवल त्रुटि है ।

    #!/bin/zsh

    #!/bin/bash

जवाबों:


26

कौन सी शेल स्क्रिप्ट का निष्पादन करती है जब शुरुआत में कोई शेबंग लाइन (#! / Path / to / shell) नहीं होती है? मैं मान / बिन / श लेकिन मैं पुष्टि नहीं कर सकता।

कर्नेल ऐसी स्क्रिप्ट और रिटर्न को निष्पादित करने के लिए मना कर दिया ENOEXEC, इसलिए सही व्यवहार कार्यक्रम पर निर्भर करता है आप इस तरह के एक स्क्रिप्ट चलाने से

  • बैश 4.2.39 - स्वयं का उपयोग करता है
  • बिजीबॉक्स-एश 1.20.2 - स्वयं का उपयोग करता है
  • डैश 0.5.7 - रन / बिन / श
  • मछली 1.23.1 - ENOEXEC के बारे में शिकायत करता है, तो गलत फाइल को दोष देता है
  • AT & T ksh 93u + 2012.08.01 - स्वयं का उपयोग करता है
  • mksh R40f - रन / बिन / श
  • pdksh 5.2.14 - रन / बिन / श
  • sh-heirloom 050706 - स्वयं उपयोग करता है
  • tcsh 6.18.01 - रन / बिन / श
  • zsh 5.0.0 - रन / बिन / श
  • cmd.exe 5.1.2600 - आपको मज़ेदार लगता है।

में glibc , कार्यों execv()या execve()बस ENOEXEC लौट आते हैं। लेकिन execvp()इस त्रुटि कोड को छुपाता है और स्वचालित रूप से इनवॉइस / बिन / श। (यह निष्पादन में प्रलेखित है (3p) ।)

शेल स्क्रिप्ट लिखने के संदर्भ में "सर्वोत्तम प्रथाओं" को क्या माना जाता है जो किसी भी मंच पर चलेगा? (ठीक है, यह ओपन-एंड की तरह है)

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

(अब जब कि मैं इसके बारे में सोचता हूं, तो पर्ल - या शायद पायथन - और भी अधिक पोर्टेबल होगा, एक बेहतर माहौल होने का उल्लेख नहीं करने के लिए।)

हमेशा शेबिंग लाइन जोड़ें। यदि बैश या zsh का उपयोग कर रहे हैं, #!/usr/bin/env bashतो शेल के पथ को हार्डकोड करने के बजाय उपयोग करें । (हालांकि, POSIX शेल पर होने की गारंटी है /bin/sh, इसलिए envउस स्थिति में छोड़ दें ।)

(दुर्भाग्य से, यहां तक /bin/shकि हमेशा समान नहीं है। जीएनयू ऑटोकॉन्फ़ कार्यक्रम को कई अलग-अलग quirks से निपटना पड़ता है ।)

क्या यह एक स्क्रिप्ट लिखना संभव है जो zsh का उपयोग करने की कोशिश करता है और अगर zsh उपलब्ध नहीं है तो वापस बश करने के लिए गिर जाता है? मैंने नीचे की तरह दो शेबंग लाइनें डालने की कोशिश की है, लेकिन यह सिर्फ खराब दुभाषिया के साथ त्रुटियां करता है : / बिन / zsh: अगर मैं बिना zsh मशीन पर इसे आज़माता हूं तो ऐसी कोई फ़ाइल या निर्देशिका नहीं है

केवल एक ही शबंग रेखा हो सकती है; न्यूलाइन वर्ण के बाद सब कुछ कर्नेल द्वारा पढ़ा भी नहीं जाता है, और गोले द्वारा टिप्पणी के रूप में माना जाता है।

यह संभव एक स्क्रिप्ट है कि रन के रूप में लिखने के लिए #!/bin/sh, चेक जो खोल उपलब्ध है, और रन exec zsh "$0" "$@"या exec bash "$0" "$@"परिणाम के आधार पर। हालाँकि, बाश और zsh द्वारा प्रयुक्त वाक्यविन्यास विभिन्न स्थानों पर इतना अलग है कि मैं आपकी खुद की पवित्रता के लिए ऐसा करने की सलाह नहीं दूंगा ।


1
जब आप ENOEXEC को प्राप्त करते हैं तो आप वास्तव में कॉल कैसे कर रहे थे, इसका पता कैसे लगाया?
स्वैगेल

2
@ सर्बेल: उपयोग करना strace -f -e fork,clone,execve/bin/shविफलता के बाद निष्पादन के लिए कुछ गोले चले गए ; अन्य लोगों ने स्वयं स्क्रिप्ट की व्याख्या की।
ग्रैविटी

1
@SWrobel: एक अन्य विधि एक स्क्रिप्ट को चलाने के लिए है जिसमें शामिल हैं readlink /proc/$$/exe
ग्रैविटी


1
के लिए cshऔर tcsh, व्यवहार कि क्या स्क्रिप्ट के साथ शुरू होता है पर निर्भर करता है #(इस स्थिति वे खुद के बजाय श आह्वान में स्क्रिप्ट व्याख्या करने के लिए)। यह उस समय तक जाता है जब csh ने टिप्पणियों का समर्थन किया #था , लेकिन बॉर्न शेल का नहीं, इसलिए एक संकेत था कि यह एक csh स्क्रिप्ट थी।
21

2

1) आपके द्वारा चलाए जा रहे वर्तमान शेल (जो भी शेल हो सकता है)

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

3) वास्तव में "if-then-अन्यथा" तर्क नहीं है interpreter directive। आपको एक शेल निर्दिष्ट करना चाहिए जो उन सभी प्रणालियों पर मौजूद होना चाहिए जिन्हें आप समर्थन करना चाहते हैं ... यानी जब तक आपकी स्क्रिप्ट सभी शेल में काफी सामान्य न हो जाए तब तक #!/bin/bashएक जेनेरिक निर्दिष्ट करें #!/bin/sh

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