जब कोई शेल स्क्रिप्ट शुरू होती है #!
, तो वह पहली पंक्ति एक टिप्पणी होती है जहां तक शेल का संबंध है। हालाँकि पहले दो अक्षर सिस्टम के दूसरे भाग के लिए सार्थक हैं: कर्नेल। दो पात्रों #!
को एक शबंग कहा जाता है । शेबंग की भूमिका को समझने के लिए, आपको यह समझने की आवश्यकता है कि किसी प्रोग्राम को कैसे निष्पादित किया जाता है।
फ़ाइल से प्रोग्राम को निष्पादित करने के लिए कर्नेल से कार्रवाई की आवश्यकता होती है। यह execve
सिस्टम कॉल के हिस्से के रूप में किया जाता है । कर्नेल को फ़ाइल अनुमतियों को सत्यापित करने की आवश्यकता है, वर्तमान में कॉल करने की प्रक्रिया में चल रही निष्पादन योग्य फ़ाइल से मुक्त संसाधन (मेमोरी, आदि), नई निष्पादन योग्य फ़ाइल के लिए संसाधन आवंटित करें, और नए प्रोग्राम (और अधिक चीजें) के लिए नियंत्रण स्थानांतरित करें। मैं उल्लेख नहीं करूंगा)। execve
सिस्टम कॉल वर्तमान में चल प्रक्रिया के कोड की जगह; fork
एक नई प्रक्रिया बनाने के लिए एक अलग सिस्टम कॉल है।
ऐसा करने के लिए, कर्नेल को निष्पादन योग्य फ़ाइल के प्रारूप का समर्थन करना होगा। इस फ़ाइल में मशीन कोड होता है, जिसे इस तरह से व्यवस्थित किया जाता है कि कर्नेल समझता है। एक शेल स्क्रिप्ट में मशीन कोड नहीं होता है, इसलिए इसे इस तरह से निष्पादित नहीं किया जा सकता है।
शेबबैंग तंत्र कर्नेल को दूसरे प्रोग्राम में कोड की व्याख्या करने के कार्य को स्थगित करने की अनुमति देता है। जब कर्नेल देखता है कि निष्पादन योग्य फ़ाइल के साथ शुरू होता है #!
, तो यह अगले कुछ वर्णों को पढ़ता है और फ़ाइल की पहली पंक्ति की व्याख्या करता है ( #!
एक और फ़ाइल के लिए पथ के रूप में अग्रणी और वैकल्पिक स्थान) (प्लस तर्क, जिसके बारे में मैं यहां चर्चा नहीं करूंगा )। जब कर्नेल को फ़ाइल निष्पादित करने के लिए कहा जाता है /my/script
, और यह देखता है कि फ़ाइल लाइन से शुरू होती है #!/some/interpreter
, तो कर्नेल /some/interpreter
तर्क के साथ निष्पादित होता है /my/script
। फिर यह /some/interpreter
तय करना है कि /my/script
यह एक स्क्रिप्ट फ़ाइल है जिसे इसे निष्पादित करना चाहिए।
क्या होगा यदि किसी फ़ाइल में न तो मूल कोड होता है जो उस प्रारूप में होता है जिसे कर्नेल समझता है, और एक शेलबैंग से शुरू नहीं होता है? ठीक है, तो फ़ाइल निष्पादन योग्य नहीं है, और execve
सिस्टम कोड त्रुटि कोड ENOEXEC
(निष्पादन योग्य प्रारूप त्रुटि) के साथ विफल हो जाता है ।
यह कहानी का अंत हो सकता है, लेकिन अधिकांश गोले एक कमबैक सुविधा को लागू करते हैं। यदि कर्नेल लौटता है ENOEXEC
, तो शेल फ़ाइल की सामग्री को देखता है और जाँचता है कि क्या यह शेल स्क्रिप्ट की तरह दिखता है। यदि शेल को लगता है कि फ़ाइल शेल स्क्रिप्ट की तरह दिखती है, तो वह इसे स्वयं निष्पादित करता है। यह कैसे करता है इसका विवरण शेल पर निर्भर करता है। आप ps $$
अपनी स्क्रिप्ट में जोड़कर क्या हो रहा है, कुछ और देख सकते हैं और इस प्रक्रिया को देखने के साथ strace -p1234 -f -eprocess
जहां 1234 शेल की पीआईडी है।
बैश में, कॉलबैक तंत्र को कॉल करके लागू किया जाता है fork
लेकिन नहीं execve
। चाइल्ड बैश प्रक्रिया अपनी आंतरिक स्थिति को अपने आप साफ कर देती है और इसे चलाने के लिए नई स्क्रिप्ट फ़ाइल को खोलती है। इसलिए स्क्रिप्ट चलाने वाली प्रक्रिया अभी भी मूल बैश कोड छवि का उपयोग कर रही है और मूल कमांड लाइन तर्क पास किए गए जब आपने मूल रूप से बैश का आह्वान किया था। ATT ksh उसी तरह से व्यवहार करता है।
% bash --norc
bash-4.3$ ./foo.sh
PID TTY STAT TIME COMMAND
21913 pts/2 S+ 0:00 bash --norc
इसके विपरीत, डैश एक तर्क के रूप में पारित स्क्रिप्ट के पथ के साथ ENOEXEC
कॉल करके प्रतिक्रिया करता है /bin/sh
। दूसरे शब्दों में, जब आप डैश से एक शेल्गबुल स्क्रिप्ट का निष्पादन करते हैं, तो यह ऐसा व्यवहार करता है जैसे कि स्क्रिप्ट में शेलबैंग लाइन होती है #!/bin/sh
। Mksh और zsh एक ही तरह से व्यवहार करते हैं।
% dash
$ ./foo.sh
PID TTY STAT TIME COMMAND
21427 pts/2 S+ 0:00 /bin/sh ./foo.sh