मैं एक वैरिएबल क्यों नहीं प्रिंट कर सकता हूँ जो मैं env के आउटपुट में देख सकता हूँ?


9

मुझे दूसरे से एक शेल उदाहरण के पर्यावरण चर को स्थापित करने में दिलचस्पी है। इसलिए मैंने कुछ शोध करने का फैसला किया। एक को पढ़ने के बाद संख्या के सवाल के बारे में इस मैं इसे बाहर का परीक्षण करने का फैसला किया।

मैंने दोनों गोले A और B (PID 420) को चलाया, दोनों चल रहे थे zsh। शेल से एआई ने निम्नलिखित भाग किया।

sudo gdb -p 420
(gdb) call setenv("FOO", "bar", 1)
(gdb) detach

शेल बी से जब मैं दौड़ता envहूं तो मैं देख सकता हूं कि वेरिएबल FOO वास्तव में बार के मान के साथ सेट है। इससे मुझे लगता है कि FOO को शेल बी के वातावरण में सफलतापूर्वक आरंभीकृत किया गया है। हालांकि, अगर मैं FOO को प्रिंट करने का प्रयास करता हूं तो मुझे एक खाली लाइन मिलती है जिसका अर्थ है कि यह सेट नहीं है। मेरे लिए, ऐसा लगता है कि यहाँ एक विरोधाभास है।

यह मेरे अपने आर्क जीएनयू / लिनक्स सिस्टम और एक उबंटू वीएम दोनों पर परीक्षण किया गया था। मैंने इस पर भी परीक्षण किया bashकि चर भी env में नहीं दिखा था। हालांकि यह मेरे लिए निराशाजनक है, यह समझ में आता है कि यदि शेल स्पॉन समय पर अपने पर्यावरण की एक प्रति को कैश करता है और केवल उसी का उपयोग करता है (जो लिंक किए गए प्रश्नों में से एक में सुझाया गया था)। यह अभी भी जवाब नहीं zshदेता है कि चर क्यों देख सकते हैं।

echo $FOOखाली का उत्पादन क्यों होता है ?


संपादित करें

टिप्पणियों में इनपुट के बाद मैंने कुछ और परीक्षण करने का फैसला किया। परिणाम नीचे दी गई तालिकाओं में देखे जा सकते हैं। पहले कॉलम में वह शेल है जिसे FOOवेरिएबल में इंजेक्ट किया गया था। पहली पंक्ति में कमांड होती है जिसका आउटपुट इसके नीचे देखा जा सकता है। चर FOOका उपयोग करके इंजेक्ट किया गया था sudo gdb -p 420 -batch -ex 'call setenv("FOO", "bar", 1)':। Zsh के लिए विशिष्ट कमांड: zsh -c '...'बैश का उपयोग करके भी परीक्षण किया गया। परिणाम समान थे, उनका उत्पादन संक्षिप्तता के लिए छोड़ा गया था।

आर्क GNU / Linux, zsh 5.3.1, बैश 4.4.12 (1)

|      |  env | grep FOO  | echo $FOO |  zsh -c 'env | grep FOO'  |  zsh -c 'echo $FOO'  |         After export FOO          |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh  |  FOO=bar         |           | FOO=bar                   | bar                  | No Change                         |
| bash |                  | bar       |                           |                      | Value of FOO visible in all tests |

Ubuntu 16.04.2 LTS, zsh 5.1.1, बैश 4.3.48 (1)

|      |  env | grep FOO  | echo $FOO |  zsh -c 'env | grep FOO'  |  zsh -c 'echo $FOO'  |         After export FOO          |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh  |  FOO=bar         |           | FOO=bar                   | bar                  | No Change                         |
| bash |                  | bar       |                           |                      | Value of FOO visible in all tests |

उपरोक्त का अर्थ है कि परिणाम वितरण अज्ञेय हैं। यह मुझे बहुत अधिक नहीं बताता है zshऔर bashचर की सेटिंग को अलग तरीके से संभालता है। इसके अलावा, export FOOशेल के आधार पर इस संदर्भ में बहुत अलग व्यवहार है। उम्मीद है कि ये परीक्षण किसी और के लिए कुछ स्पष्ट कर सकते हैं।


क्या होता है, अगर आप zsh -c 'echo $FOO'इसके बजाय एक (एकल उद्धरण का उपयोग करें!) करते हैं क्या आप इसे देख सकते हैं?
user1934428

सही मूल्य एक नए उप शेल से मुद्रित किया गया है (बैश बच्चे के लिए भी परीक्षण किया गया है)। स्पष्ट रूप से पर्यावरण किसी भी तरह से स्थायी है क्योंकि बच्चा इसे विरासत में दे सकता है लेकिन माता-पिता इसे सम्मान क्यों नहीं देते?
RLF

3
बिल्कुल यही मैने सोचा। मुझे लगता है कि शेल में कहीं न कहीं चर का प्रतीक तालिका है, उनमें से कुछ को "निर्यात" के रूप में चिह्नित किया गया है, जिसका अर्थ है कि एक उपधारा खोलने पर, उन्हें बाल प्रक्रिया के वातावरण में रखा गया है। प्रारंभ में (जब शेल शुरू होता है), उस समय पर्यावरण से चर को प्रतीक तालिका (निश्चित रूप से "निर्यात" चर) के रूप में कॉपी किया जाता है। जब आप पर्यावरण बदलते हैं, तो शेल को उनकी प्रतीक तालिका को अपडेट करने के लिए नोटिस नहीं किया जाता है - लेकिन बच्चे की प्रक्रिया (जैसे env) संशोधित वातावरण को देखते हैं।
user1934428

2
मैंने Ubuntu 16.04 पर zsh 5.1.1 और bash 4.3.48 (1) के साथ परीक्षण किया और ऐसा लगता है zshकि GDB के लिए एक पर्यावरण चर सेट करना इसे शेल चर के रूप में दिखाई नहीं देता है, लेकिन इसका कारण बाल प्रक्रियाओं को पारित करना है (के रूप में) आप) देखा है, के लिए एक सेट करते समय bash करता है यह एक खोल चर के रूप में दिखाई दे रहा है, लेकिन है नहीं यह बच्चे प्रक्रियाओं को पारित करने के लिए कारण हो! ऐसा लगता है कि zsh और bash वैरिएबल के प्रबंधन के लिए अलग-अलग रणनीतियों का उपयोग करते हैं, zsh ट्रैकिंग नॉन-एनवायरनमेंट वैरिएबल के साथ और अपने वातावरण में हर चीज को स्टोर करने के लिए, जिसे वह (नॉन-सबशेल) बच्चे को लॉन्च करते समय साफ करता है।
एलियाह कगन

@ एलियाकगन, दिलचस्प; आपको उत्तर के रूप में पोस्ट करना चाहिए। मुझे आश्चर्य है कि अगर आप इसमें भाग लेते हैं तो क्या फर्क पड़ता export FOOहै bash?
वाइल्डकार्ड

जवाबों:


2

अधिकांश गोले getenv()/ setenv()/ putenv()एपीआई का उपयोग नहीं करते हैं ।

स्टार्ट-अप पर, वे प्रत्येक पर्यावरण चर के लिए शेल चर बनाते हैं। उन आंतरिक संरचनाओं में संग्रहीत किया जाएगा जिन्हें अन्य जानकारी ले जाने की आवश्यकता है जैसे कि चर निर्यात किया जाता है, केवल-पढ़ने के लिए ... वे इसके लिए libc का उपयोग नहीं कर सकते हैं environ

इसी तरह, और इस कारण से, वे कमांड निष्पादित करने के लिए उपयोग नहीं करेंगे execlp(), execvp()लेकिन execve()सिस्टम कॉल को सीधे कॉल करें, envp[]अपने निर्यात किए गए चर की सूची के आधार पर सरणी की गणना करें ।

तो आपके लिए gdb, आपको उस गोले की आंतरिक तालिका के लिए एक प्रविष्टि जोड़ने की आवश्यकता होगी, या संभवतः सही फ़ंक्शन को कॉल करें जो इसे export VAR=valueउस तालिका को खुद से अपडेट करने के लिए एक कोड की व्याख्या करेगा ।

जैसा कि आप के बीच एक अंतर क्यों देखते हैं bashऔर zshजब आप कॉल करते setenv()हैं gdb, मुझे संदेह है कि क्योंकि आप setenv()शेल इनिशियल्स से पहले कॉल कर रहे हैं , उदाहरण के लिए प्रवेश करने पर main()

आप देखेंगे bashकी main()है int main(int argc, char* argv[], char* envp[])(और bashनक्शे चर से उन env में वार्स envp[]), जबकि zsh's है int main(int argc, char* argv[])और zshसे चर हो जाता है environबजाय। setenv()संशोधित करता है, environलेकिन envp[]इन-प्लेस (केवल कई सिस्टम पर और साथ ही उन बिंदुओं को इंगित करता है) को संशोधित नहीं कर सकता ।

किसी भी स्थिति में, शेल ने environस्टार्टअप पर पढ़ा है, का उपयोग setenv()करना अप्रभावी होगा क्योंकि शेल अब उपयोग नहीं करता है environ(या getenv()) बाद में।

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