गोले के गोले क्या हो सकते हैं?


42

मैं सिर्फ एक समस्या में भाग गया, जो मुझे दिखाता है कि मैं शेल चर के दायरे पर स्पष्ट नहीं हूं।

मैं उपयोग करने की कोशिश कर रहा था bundle install, जो एक रूबी कमांड है जो $GEM_HOMEअपने काम करने के लिए मूल्य का उपयोग करता है । मैंने सेट $GEM_HOMEकर दिया था , लेकिन कमांड ने उस मूल्य को अनदेखा कर दिया, जब तक मैंने उपयोग नहीं किया export, जैसा कि अंदर था export GEM_HOME=/some/path

मैंने पढ़ा कि यह चर को किसी भी तरह "वैश्विक" ( पर्यावरण चर के रूप में भी जाना जाता है ) बनाता है , लेकिन मुझे इसका मतलब समझ में नहीं आता है। मैं प्रोग्रामिंग में ग्लोबल्स के बारे में जानता हूं, लेकिन अलग-अलग कार्यक्रमों में नहीं।

यह भी, यह देखते हुए कि मेरी सेटिंग इस तरह के चर केवल वर्तमान शेल सत्र पर लागू होती है, मैं उन्हें कैसे निर्धारित करूं, एक निर्धारित प्रक्रिया?

गोले के गोले क्या हो सकते हैं?

जवाबों:


33

प्रक्रियाओं एक पेड़ के रूप में आयोजित किया जाता है: हर प्रक्रिया के लिए एक अनूठा माता पिता, से अलग है initजो PIDहमेशा 1 है और कोई पैरेंट है।

एक नई प्रक्रिया का निर्माण आम तौर पर एक जोड़ी fork/ execvसिस्टम कॉल के माध्यम से होता है , जहां बच्चे की प्रक्रिया का वातावरण मूल प्रक्रिया की एक प्रति है।

उस चर से पर्यावरण में एक चर रखने के लिए, आपको exportउस चर पर जाना होगा, ताकि यह सभी बच्चों को पुनरावर्ती दिखाई दे। लेकिन इस बात से अवगत रहें कि यदि कोई बच्चा किसी चर के मूल्य को बदलता है, तो परिवर्तित मूल्य केवल उसे दिखाई देता है और उस परिवर्तन के बाद बनाई गई सभी प्रक्रियाएं ( प्रतिलिपि होने के नाते , जैसा कि पहले कहा गया है)।

यह भी ध्यान में रखें कि एक बच्चा प्रक्रिया अपने वातावरण को बदल सकती है, उदाहरण के लिए इसे डिफ़ॉल्ट मानों पर रीसेट कर सकती है, जैसा कि संभवतः loginउदाहरण के लिए किया जाता है ।


1
आह! ठीक है, चलो देखते हैं कि क्या मैं इसे समझता हूं। शेल में, अगर मैं कहता हूं FOO=bar, कि वर्तमान शेल प्रक्रिया के लिए मान सेट करता है। अगर मैं फिर एक प्रोग्राम (जैसे bundle install) चलाता हूं, तो एक चाइल्ड प्रोसेस बनता है, जिसे एक्सेस नहीं मिलता है FOO। लेकिन अगर मैंने कहा होता export FOO=bar, तो बाल प्रक्रिया (और उसके वंशज) उस तक पहुँच पाती । उनमें से एक, बदले में, export FOO=buzzअपने वंशजों के लिए मूल्य बदलने के लिए कॉल कर सकता है, या केवल अपने FOO=buzzलिए मूल्य बदल सकता है। क्या यह सही है?
नाथन लोंग

2
@ नथानलॉन्ग वास्तव में ऐसा नहीं है: सभी आधुनिक गोले में, एक चर या तो निर्यात किया जाता है (और इसलिए मूल्य में कोई भी परिवर्तन वंशजों के वातावरण में परिलक्षित होता है) या निर्यात नहीं किया जाता है (जिसका अर्थ है कि चर पर्यावरण में नहीं है)। विशेष रूप से, यदि शेल शुरू होने पर चर पहले से ही पर्यावरण में है, तो इसे निर्यात किया जाता है।
गाइल्स का SO- बुराई पर रोक '16

2
मैं वाक्य से थोड़ा उलझन में था "अगर एक बच्चा एक चर के मूल्य को बदलता है, तो परिवर्तित मूल्य केवल इसके लिए दिखाई देता है और उस परिवर्तन के बाद बनाई गई सभी प्रक्रियाएं"। यह कहना अधिक सही होगा "... यह दिखाई देता है और उस परिवर्तन के बाद बनाई गई इसकी सभी अवरोही प्रक्रियाएं" - माता-पिता की प्रक्रिया के दूसरे बच्चे, यहां तक ​​कि वे जो बच्चे की प्रक्रिया के बाद शुरू हुए, प्रभावित नहीं होते हैं।
जान

26

कम से कम के तहत kshऔर bash, चर में तीन स्कोप हो सकते हैं , दो नहीं जैसे सभी शेष उत्तर वर्तमान में बता रहे हैं।

निर्यात किए गए (यानी पर्यावरण) चर और शेल के बिना निर्यात किए गए वैरिएबल स्कोप के अलावा, फ़ंक्शन चर चर के लिए एक तीसरा संकरा भी है।

typesetटोकन के साथ शेल फ़ंक्शन में घोषित चर केवल उन कार्यों के अंदर दिखाई देते हैं जिन्हें वे (उप) कार्यों में घोषित किए जाते हैं।

यह ksh/ bashकोड:

# Create a shell script named /tmp/show that displays the scoped variables values.    
echo 'echo [$environment] [$shell] [$local]' > /tmp/show
chmod +x /tmp/show

# Function local variable declaration
function f
{
    typeset local=three
    echo "in function":
    . /tmp/show 
}

# Global variable declaration
export environment=one

# Unexported (i.e. local) variable declaration
shell=two

# Call the function that creates a function local variable and
# display all three variable values from inside the function
f

# Display the three values from outside the function
echo "in shell":
. /tmp/show 

# Display the same values from a subshell
echo "in subshell":
/tmp/show

# Display the same values from a disconnected shell (simulated here by a clean environment start)
echo "in other shell"
env -i /tmp/show 

इस उत्पादन का उत्पादन:

in function:
[one] [two] [three]
in shell:
[one] [two] []
in subshell:
[one] [] []
in other shell
[] [] []

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

ध्यान दें कि यह बाद वाला व्यवहार विंडोज एक से काफी अलग है जहां आप सिस्टम वेरिएबल्स का उपयोग कर सकते हैं जो पूरी तरह से वैश्विक हैं और सभी प्रक्रियाओं द्वारा साझा किए गए हैं।


12

उन्हें प्रक्रिया से अलग कर दिया जाता है

अन्य उत्तरदाताओं ने मुझे यह समझने में मदद की कि शेल चर गुंजाइश प्रक्रियाओं और उनके वंशजों के बारे में है

जब आप lsकमांड लाइन पर एक कमांड टाइप करते हैं, तो आप वास्तव में lsप्रोग्राम को चलाने के लिए एक प्रक्रिया के लिए धन्यवाद कर रहे हैं । नई प्रक्रिया में आपका खोल अपने मूल के रूप में है।

किसी भी प्रक्रिया के अपने "स्थानीय" चर हो सकते हैं, जो कि बाल प्रक्रियाओं में पारित नहीं होते हैं। यह "पर्यावरण" चर भी सेट कर सकता है, जो हैं। उपयोग करने exportसे वातावरण परिवर्तनशील बनता है। या तो मामले में, असंबंधित प्रक्रियाएं (मूल के साथी) चर नहीं देखेंगे; हम केवल वही नियंत्रित कर रहे हैं जो बच्चे प्रक्रियाएं देखते हैं।

मान लीजिए आप एक bash खोल, जो हम ए आप टाइप फोन करता हूँ है bash, जो एक बच्चे की प्रक्रिया बैश खोल, जो हम बी कुछ भी फोन करता हूँ आप कहा जाता है बनाता है exportअभी भी बी में स्थापित किया जाएगा एक में पर

अब, B में, आप कहते हैं FOO=b। दो चीजों में से एक होगा:

  • यदि B को (A) से पर्यावरण चर नहीं कहा जाता है FOO, तो उसे स्थानीय चर प्राप्त होगा। B के बच्चे इसे प्राप्त नहीं करेंगे (जब तक कि B कॉल न करें export)।
  • तो बी था (ए) से प्राप्त एक वातावरण चर callled FOO, यह होगा वह खुद को और उसके बाद में काँटेदार बच्चों के लिए संशोधित । B के बच्चे को वह मान दिखाई देगा जो B को सौंपा गया है। हालांकि, यह ए को बिल्कुल भी प्रभावित नहीं करेगा।

यहाँ एक त्वरित डेमो है।

FOO=a      # set "local" environment variable
echo $FOO  # 'a'
bash       # forks a child process for the new shell
echo $FOO  # not set
exit       # return to original shell
echo $FOO  # still 'a'

export FOO # make FOO an environment variable
bash       # fork a new "child" shell
echo $FOO  # outputs 'a'
FOO=b      # modifies environment (not local) variable
bash       # fork "grandchild" shell
echo $FOO  # outputs 'b'
exit       # back to child shell
exit       # back to original shell
echo $FOO  # outputs 'a'

यह सब मेरी मूल समस्या की व्याख्या करता है: मैं GEM_HOMEअपने शेल में सेट करता हूं, लेकिन जब मैंने कॉल किया bundle install, तो उसने एक बाल प्रक्रिया बनाई। क्योंकि मैंने इस्तेमाल नहीं किया था export, बच्चे की प्रक्रिया को शेल प्राप्त नहीं हुआ था GEM_HOME

संयुक्त राष्ट्र के निर्यात

आप एक वेरिएबल को "अन-एक्सपोर्ट" कर सकते हैं - इसे बच्चों को पास करने से रोकें - उपयोग करके export -n FOO

export FOO=a   # Set environment variable
bash           # fork a shell
echo $FOO      # outputs 'a'
export -n FOO  # remove environment var for children
bash           # fork a shell
echo $FOO      # Not set
exit           # back up a level
echo $FOO      # outputs 'a' - still a local variable

1
जब आप कहते हैं "यह इसे अपने और अपने बच्चों के लिए संशोधित करेगा" तो आपको यह स्पष्ट करना चाहिए कि संशोधन के बाद बनाए गए बच्चे केवल संशोधित मूल्य देखेंगे।
enzotib

1
@enzotib - अच्छी बात है। अपडेट किया गया।
नाथन लांग

3

सबसे अच्छा स्पष्टीकरण मैं निर्यात के बारे में पा सकता हूं यह एक है:

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html

एक उप-समूह या बच्चे के खोल के भीतर सेट किया गया चर केवल उस उप-समुच्चय के लिए दृश्यमान होता है जिसमें इसे परिभाषित किया गया है। निर्यातित चर वास्तव में एक पर्यावरण चर है। तो स्पष्ट होने के लिए bundle installअपने स्वयं के शेल निष्पादित करता है जो $GEM_HOMEतब तक नहीं देखता है जब तक कि इसे environmentनिर्यात किए गए चर उर्फ ​​नहीं बनाया जाता है।

आप यहाँ चर क्षेत्र के लिए प्रलेखन पर एक नज़र डाल सकते हैं:

http://www.tldp.org/LDP/abs/html/subshells.html


आह, इसलिए मैं "पर्यावरण चर" शब्द का उपयोग करने के लिए गलत था FOO=bar; आपको exportइसे एक बनाने के लिए उपयोग करना होगा। तदनुसार प्रश्न सही हो गया।
नाथन लॉन्ग

मेरे द्वारा जोड़े गए लिंक पर एक नज़र डालें।
कार्लसन

3

उम्मीद के मुताबिक, चर स्कोप्स का एक पदानुक्रम है।

वातावरण

सबसे बाहरी क्षेत्र पर्यावरण है। यह ऑपरेटिंग सिस्टम द्वारा प्रबंधित एकमात्र क्षेत्र है और इसलिए हर प्रक्रिया के लिए मौजूद होने की गारंटी है। जब कोई प्रक्रिया शुरू की जाती है तो उसे अपने माता-पिता के वातावरण की एक प्रति प्राप्त होती है जिसके बाद दोनों स्वतंत्र हो जाते हैं: बच्चे के पर्यावरण को संशोधित करने से माता-पिता का परिवर्तन नहीं होता है, और माता-पिता के वातावरण को संशोधित करने से पहले से मौजूद बच्चे का परिवर्तन नहीं होता है।

शैल चर

गोले चर की अपनी धारणा है। यहीं से चीजें थोड़ी गड़बड़ होने लगती हैं।

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

यहाँ वह जगह है जहाँ exportकीवर्ड खेल में आता है। यह शेल प्रक्रिया के वातावरण में एक शेल वैरिएबल की प्रतिलिपि बनाता है जिससे यह संभव है कि बच्चे की प्रक्रियाएं वंशानुक्रम के लिए संभव हों।

स्थानीय चर

स्थानीय वैरिएबल शेल वैरिएबल होते हैं जिन्हें कोड ब्लॉक में रखा जाता है। आप typesetकीवर्ड (पोर्टेबल) localया declare(बाश) के साथ स्थानीय चर घोषित करते हैं । अन्य शेल चरों की तरह स्थानीय चर भी बाल प्रक्रियाओं द्वारा विरासत में नहीं मिले हैं। इसके अलावा स्थानीय चर निर्यात नहीं किया जा सकता है।

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