एक उप-संस्करण में एक चर क्यों दिखाई दे रहा है?


18

लर्निंग बैश बुक में उल्लेख किया गया है कि एक उपधारा केवल पर्यावरण चर और फ़ाइल विवरणक, इत्यादि का वारिस करेगा, और यह कि निर्यात नहीं होने वाले चर विरासत में नहीं मिलेंगे:

$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var

$

जैसा कि मुझे पता है कि शेल के लिए ()और इसके लिए दो उप-खंड बनाए जाएंगे ./file, लेकिन ()मामले में उप- varचर चर की पहचान क्यों करता है हालांकि यह निर्यात नहीं किया जाता है और ./fileमामले में इसकी पहचान नहीं की गई है?

# Strace for () 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631

मैंने straceयह पता लगाने की कोशिश की कि यह कैसे होता है और आश्चर्यजनक रूप से मैंने पाया कि बैश क्लोन सिस्टम कॉल के लिए एक ही तर्क का उपयोग करेगा, तो इसका मतलब है कि दोनों में कांटे की प्रक्रिया ()और ./fileमाता-पिता की समान प्रक्रिया पता स्थान होनी चाहिए, इसलिए में ()मामला subshell को दिखाई varible है और उसी के लिए नहीं होता है ./file, हालांकि एक ही तर्क क्लोन सिस्टम कॉल पर आधारित है, मामला?


vinc17 सच कहो, यहां तक ​​कि जब आप सबस्क्राइब हो जाते हैं, तब आप इस बात को मानते हैं।
फारसगुल्फ

जवाबों:


15

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

नोट: यह बैश करने के लिए विशिष्ट नहीं है; यह किसी भी शेल के लिए सही है।


Oky, लेकिन मैंने अब शैल पर स्ट्रेच की प्रशंसा करने की कोशिश की और मैंने निष्पादित करने का प्रयास किया ।/file लेकिन मुझे निष्पादन के लिए कोई कॉल नहीं मिला और इसलिए दोनों प्रक्रियाओं के लिए पता स्थान एक ही होना चाहिए ताकि यह कैसे समझाया जा सके?
user3718463

@ user3718463 क्या आपने बच्चों को भी ट्रेस करने के -fविकल्प का उपयोग किया straceहै? यह निष्पादन को खोजने के लिए आवश्यक है।
vinc17

हाँ, मैं यह पता लगाने के लिए बहुत बहुत धन्यवाद, मैं -f विकल्प याद आ रही थी, और इसलिए मैं निष्पादन फोन नहीं मिल सकता है
user3718463

16

या तो आप या पुस्तक एक उपप्रकार के साथ एक उपप्रकार को भ्रमित कर रही है जो एक शेल है।

कुछ खोल निर्माणों खोल में परिणाम forking एक बच्चे की प्रक्रिया। लिनक्स के तहत, forkअधिक सामान्य cloneसिस्टम कॉल का एक विशेष मामला है , जिसे आपने straceलॉग में देखा था । बच्चा शेल स्क्रिप्ट का एक हिस्सा चलाता है। बच्चे की प्रक्रिया को एक उपधारा कहा जाता है । इस तरह का सबसे प्रत्यक्ष निर्माण है command1 &: command1एक सब-रन में चलता है, और बाद में कमांड पैरेंट शेल में चलता है। उप-निर्माण बनाने वाले अन्य निर्माणों में कमांड प्रतिस्थापन $(command2)और पाइप शामिल हैं command3 | command4( command3एक उप-प्रकार में command4चलता है , अधिकांश शेल में एक उप-भाग में चलता है लेकिन ksh या zsh में नहीं)।

एक उपधारा मूल प्रक्रिया की एक प्रति है, इसलिए इसमें न केवल एक ही पर्यावरण चर है, बल्कि सभी समान आंतरिक परिभाषाएं भी हैं: चर ( $$मूल शेल प्रक्रिया की प्रक्रिया आईडी), फ़ंक्शन, उपनाम, विकल्प आदि। उपधारा में कोड को निष्पादित करने से पहले, बैश चर BASHPIDको बाल प्रक्रिया की आईडी में सेट करता है।

जब आप चलाते हैं ./file, तो यह एक बाहरी कमांड निष्पादित करता है। सबसे पहले, शेल एक बच्चे की प्रक्रिया की तलाश करता है; तब यह बाल प्रक्रिया निष्पादन योग्य फ़ाइल के साथ ( सिस्टम कॉल के साथ) निष्पादितexecve होती है ./file। एक बच्चा प्रक्रिया अपने माता-पिता की प्रक्रिया की विशेषताओं को प्राप्त करती है: पर्यावरण, वर्तमान निर्देशिका, आदि। एप्लिकेशन में आंतरिक पहलुओं को execveकॉल में खो दिया जाता है : गैर-निर्यात किए गए चर, फ़ंक्शन, आदि ऐसे बैश विचार हैं जिनके बारे में कर्नेल को पता नहीं है, और वे खो जाते हैं जब बैश दूसरे प्रोग्राम को अंजाम देता है। यहां तक ​​कि अगर वह अन्य प्रोग्राम एक बैश स्क्रिप्ट के रूप में होता है, तो इसे एक नए उदाहरण के द्वारा निष्पादित किया जाता है, जो यह नहीं जानता या परवाह नहीं करता है कि इसकी मूल प्रक्रिया भी बैश की एक आवृत्ति है। इस प्रकार एक शेल वैरिएबल (नॉन-एक्सपोर्टेड वैरिएबल) जीवित नहीं रहता है execve


इस जवाब ने मेरे लिए काफी कुछ साफ कर दिया। केवल एक चीज जो मुझे समझ नहीं आ रही है वह दूसरे पैराग्राफ में यह वाक्य है: "बच्चा शेल स्क्रिप्ट का एक हिस्सा चलाता है।" किस शेल स्क्रिप्ट को संदर्भित किया जा रहा है?
flow2k

@ flow2k स्क्रिप्ट (यानी प्रोग्राम) जो शेल की व्याख्या कर रही है।
गिलेस एसओ- बुराई को रोकना '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.