बैश घुंघराले ब्रेसिज़ के साथ रचना को सब्सक्राइब करें


31

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

psकार्रवाई में यह देखने के लिए उपयोग करना

यह कमांड लाइन पर सीधे निष्पादित एक प्रक्रिया पाइपलाइन के लिए प्रक्रिया पदानुक्रम है। 4398 लॉगिन शेल के लिए PID है:

sleep 2 | ps -H;
  PID TTY          TIME CMD
   4398 pts/23   00:00:00 bash
   29696 pts/23   00:00:00   sleep
   29697 pts/23   00:00:00   ps

अब कमांड लाइन पर सीधे निष्पादित घुंघराले ब्रेसिज़ के बीच एक प्रक्रिया पाइपलाइन के लिए प्रक्रिया पदानुक्रम का अनुसरण करता है। 4398 लॉगिन शेल के लिए पीआईडी ​​है। यह ऊपर दिए गए पदानुक्रम के समान है जो यह साबित करता है कि सब कुछ वर्तमान शेल संदर्भ में निष्पादित किया गया है :

{ sleep 2 | ps -H; }
   PID TTY          TIME CMD
    4398 pts/23   00:00:00 bash
    29588 pts/23   00:00:00   sleep
    29589 pts/23   00:00:00   ps

अब, यह प्रक्रिया पदानुक्रम है जब sleepपाइपलाइन को घुंघराले ब्रेसिज़ के अंदर रखा जाता है (इसलिए सभी में ब्रेसिज़ के दो स्तर)

{ { sleep 2; } | ps -H; }
  PID TTY          TIME CMD
   4398 pts/23   00:00:00 bash
   29869 pts/23   00:00:00   bash
   29871 pts/23   00:00:00     sleep
   29870 pts/23   00:00:00   ps

3rd केस में bashचलने के लिए सबस्क्रिप्शन क्यों बनाना पड़ता है sleepजब प्रलेखन में कहा गया है कि घुंघराले ब्रेसिज़ के बीच कमांड को वर्तमान शेल संदर्भ में निष्पादित किया जाता है?


दिलचस्प है, मुझे लगता है कि यह 3 के मामले में है क्योंकि आंतरिक समूह पाइपलाइन का हिस्सा है, और इसलिए इसे सब-शेल जैसे, किसी अन्य फ़ंक्शन कॉल के रूप में निष्पादित किया जाता है, जो पाइपलाइन का हिस्सा है। क्या इस का कोई मतलब निकलता है?
मिरोस्लाव कोसकर

2
मैं यह नहीं कहूंगा कि "शेल को" सिर्फ इसलिए करना चाहिए क्योंकि यह होता है ... पाइपलाइन को शेल संदर्भ में निष्पादित नहीं किया जाता है। यदि पाइपलाइन में बाहरी कमांड के अलावा कुछ भी नहीं है तो उपप्रोसेस बनाना पर्याप्त है। { sleep 2 | command ps -H; }
हौके लैगिंग

जवाबों:


26

एक पाइपलाइन में, सभी कमांड अलग-अलग प्रक्रियाओं में समवर्ती (उनके स्टडआउट / पाइप द्वारा जुड़े स्टड के साथ) चलते हैं।

में

cmd1 | cmd2 | cmd3

सभी तीन आदेश अलग-अलग प्रक्रियाओं में चलते हैं, इसलिए उनमें से कम से कम दो को एक बच्चे की प्रक्रिया में चलाना पड़ता है। कुछ गोले उनमें से एक को मौजूदा शेल प्रक्रिया में चलाते हैं (यदि बिल्टिन की तरह readया यदि पाइपलाइन स्क्रिप्ट की अंतिम कमांड है), लेकिन bashउन सभी को अपनी अलग प्रक्रिया में चलाता है ( lastpipeहाल के bashसंस्करणों में विकल्प को छोड़कर और कुछ विशिष्ट परिस्थितियों में )।

{...}समूह आदेश। यदि वह समूह एक पाइपलाइन का हिस्सा है, तो उसे एक साधारण कमांड की तरह एक अलग प्रक्रिया में चलाना होगा।

में:

{ a; b "$?"; } | c

हमें मूल्यांकन करने के लिए एक शेल की आवश्यकता है जो a; b "$?"एक अलग प्रक्रिया है, इसलिए हमें एक उपधारा की आवश्यकता है। शेल को bउस समूह में चलाने के लिए अंतिम कमांड होने के कारण फोर्क न करके ऑप्टिमाइज़ किया जा सकता है। कुछ गोले ऐसा करते हैं, लेकिन स्पष्ट रूप से नहीं bash


" सभी तीन आदेश अलग-अलग प्रक्रियाओं में चलते हैं, इसलिए उनमें से कम से कम दो को एक उपधारा में चलाना होता है। " इस मामले में एक उपखंड आवश्यक क्यों है? क्या माता-पिता के खोल में पेड़ की प्रक्रिया नहीं हो सकती है? या, जब आप कहते हैं कि " एक subshell में चलाने के लिए है आप मतलब है खोल ही कांटा होगा, और फिर प्रत्येक cmd1 CMD2 और cmd3 के लिए कार्यकारी",? अगर मैं इसे अंजाम देता हूं तो मुझे bash -c "sleep 112345 | cat | cat "केवल एक बैश बना हुआ दिखाई देता है और फिर 3 बच्चे बिना किसी अन्य इंटरलेविंग सब बेस के।
हकन बाबा

" हमें यह मूल्यांकन करने के लिए एक शेल की आवश्यकता है कि ए, बी" $? "एक अलग प्रक्रिया है, इसलिए हमें एक उपधारा की आवश्यकता है। " क्या आप तर्क का विस्तार भी कर सकते हैं? हमें यह समझने के लिए एक उपधारा की आवश्यकता क्यों है? इसे समझने में क्या लगता है? मुझे लगता है कि पार्सिंग की आवश्यकता है लेकिन और क्या है? । क्या पैरेंट शेल पार्स नहीं कर सकते a; b "$?"? क्या वास्तव में एक उपशीर्ष की मूलभूत आवश्यकता है, या हो सकता है कि यह बैश पर एक डिजाइन निर्णय / कार्यान्वयन है?
हकन बाबा

@ हकनबाबा, मैंने संभावित भ्रम से बचने के लिए "चाइल्ड प्रोसेस" में बदलाव किया है।
स्टीफन चेज़लस

1
@ हाकनबाबा, अभिभावक का पालन-पोषण माता-पिता में किया जाता है (वह प्रक्रिया जो कोड को पढ़ती है, वह है जो दुभाषिया को निष्पादित करता है जब तक कि कोड पारित नहीं हुआ था eval), लेकिन मूल्यांकन (पहले कमांड को चलाएँ, इसके लिए प्रतीक्षा करें, दूसरा चलाएं) बच्चे में किया जाता है, वह है जो पाइप से जुड़ा हुआ है।
स्टीफन चेज़लस

में { sleep 2 | ps -H; }माता-पिता बैश देखता है sleep 2कि एक कांटा / कार्यकारी की आवश्यकता है। लेकिन { { sleep 2; } | ps -H; }पैरेंट बैश { sleep 2; }में दूसरे शब्दों में कुछ बैश कोड दिखता है। ऐसा लगता है कि अभिभावक कांटा / निष्पादन के लिए संभाल सकता है, sleep 2लेकिन सामना किए गए बैश कोड को संभालने के लिए एक नए बैश को पुन: बनाता है। यह मेरी समझ है, क्या इसका कोई मतलब है?
हकन बाबा

19

घुंघराले ब्रेसिज़ को घोंसले में डालना यह प्रतीत होता है कि आप एक अतिरिक्त स्तर का स्कोप बना रहे हैं जिसके लिए नए उप-शेल की आवश्यकता होती है। आप इस आशय को अपने ps -Hआउटपुट में बैश की दूसरी प्रति के साथ देख सकते हैं ।

केवल कर्ल ब्रेस के पहले स्तर में निर्धारित प्रक्रियाएं मूल बैश शेल के दायरे में चलाई जाती हैं। किसी भी नेस्टेड घुंघराले ब्रेस अपने स्वयं के स्कॉप्ड बैश शेल में चलेंगे।

उदाहरण

$ { { { sleep 20; } | sleep 20; } | ps -H; }
  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5012 pts/1    00:00:00   bash
 5014 pts/1    00:00:00     bash
 5016 pts/1    00:00:00       sleep
 5015 pts/1    00:00:00     sleep
 5013 pts/1    00:00:00   ps

| ps -Hमिश्रण से बाहर निकालते हुए, ताकि हम नेस्टेड घुंघराले ब्रेसिज़ देख सकें, हम ps auxf | lessदूसरे शेल में चला सकते हैं ।

saml     29190  0.0  0.0 117056  3004 pts/1    Ss   13:39   0:00  \_ bash
saml      5191  0.0  0.0 117056  2336 pts/1    S+   14:42   0:00  |   \_ bash
saml      5193  0.0  0.0 107892   512 pts/1    S+   14:42   0:00  |   |   \_ sleep 20
saml      5192  0.0  0.0 107892   508 pts/1    S+   14:42   0:00  |   \_ sleep 20
saml      5068  0.2  0.0 116824  3416 pts/6    Ss   14:42   0:00  \_ bash
saml      5195  0.0  0.0 115020  1272 pts/6    R+   14:42   0:00      \_ ps auxf
saml      5196  0.0  0.0 110244   880 pts/6    S+   14:42   0:00      \_ less

लेकिन रुकिए ज्यादा है!

यदि आप पाइपों को बाहर निकालते हैं और कमांड के इस रूप का उपयोग करते हैं, तो हम देखते हैं कि आप वास्तव में क्या उम्मीद करते हैं:

$ { { { sleep 10; } ; { sleep 10; } ; sleep 10; } } | watch "ps -H"

अब परिणामी घड़ी की खिड़की में हमें हर 2 सेकंड में एक अपडेट मिलता है कि क्या हो रहा है:

यहाँ पहला है sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5678 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5681 pts/1    00:00:00     watch
 5682 pts/1    00:00:00       ps

यहाँ दूसरा है sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5691 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5694 pts/1    00:00:00     watch
 5695 pts/1    00:00:00       ps

यहाँ तीसरा है sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5704 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5710 pts/1    00:00:00     watch
 5711 pts/1    00:00:00       ps

सभी तीन नींदों को नोटिस करें हालांकि घुंघराले ब्रेसिज़ के विभिन्न घोंसले के स्तर पर लगाए गए बैश के पीआईडी ​​5676 के भीतर ही रहते हैं। इसलिए मेरा मानना ​​है कि आपके मुद्दे का उपयोग करने के साथ ही आत्ममुग्ध है | ps -H

निष्कर्ष

| ps -H(यानी पाइप) का उपयोग एक अतिरिक्त उप-शेल का कारण बन रहा है, इसलिए जब जो चल रहा है, उससे पूछताछ करने का प्रयास न करें।


इसलिए, "केवल कर्ल ब्रेस के पहले स्तर में निर्धारित प्रक्रियाएं मूल बैश शेल के दायरे में चलाई जाती हैं।"
xealits

@xealits - क्या यह अनुवर्ती प्रश्न है जो आप मुझसे पूछ रहे हैं?
SLM

@ एसएलएम यह केवल उत्तर के मुख्य बिंदु पर जोर है, जैसा कि मैंने इसे देखा। वर्तमान खोल में चलने वाले घुंघराले ब्रेसिज़ के पहले स्तर के कमांड, नेस्टेड कर्ली ब्रेसिज़ नए गोले बनाते हैं। कोष्ठक पहले स्तर पर, ठीक से बनाने में भिन्न होते हैं। अगर मुझे यह गलत लगा - मुझे सुधारो। लेकिन, जैसा कि अन्य लोग बताते हैं, प्रारंभिक प्रश्न में पाइपलाइन भी हैं। इस प्रकार अलग-अलग प्रक्रियाओं का निर्माण। और घुंघराले ब्रेसिज़ को एक अलग प्रक्रिया के लिए उपयोग किए जाने पर एक शेल बनाना पड़ता है। तो, शायद, यह प्रश्न में व्यवहार का कारण है।
xealits

अब, आपके पोस्ट को पुन: प्रकाशित करने के बाद, मुझे लगता है कि मैं गलत था - घोंसले के शिकार बयान केवल पाइपलाइनों के मामले में चिंता करता है। तो, घुंघराले ब्रेसिज़ कभी भी नए गोले नहीं बनाते हैं, जब तक कि आप उनके साथ एक अलग प्रक्रिया नहीं लपेटते हैं - तब उन्हें करना होगा।
xealits

@xealits - यह सही है।
SLM

7

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

$ { A=1; { A=2; sleep 2; } ; echo $A; }
2

$ { A=1; { A=2; sleep 2; } | sleep 1; echo $A; }
1

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