2012-02-02 9 views
12

एक comment on another post में, @JonathanLeffler कहा कि:बैश सबहेल/पाइपलाइन - कौन सा भाग सबहेल में निष्पादित कर रहे हैं?

{...} | कुछ कमांड एक उप-खोल में चलाया जाता है और पैरेंट शैल को प्रभावित नहीं करता है। डेमो:

X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X

(उत्पादन PQR, एबीसी, पीक्यूआर तीन लाइनों पर साथ)

और वास्तव में:

[email protected]:tmp$X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X 
PQR 
ABC 
PQR 

हालांकि, man bash का कहना है कि { .. } करता है एक सबहेल में निष्पादित नहीं:

{ list; } 
      list is simply executed in the current shell environment. list must be 
      terminated with a newline or semicolon. This is known as a group command. 

तो यहां क्या हो रहा है? man bash गलत है? मुझे पता है कि पाइपलाइन के प्रत्येक हिस्से को सबहेल में निष्पादित किया जाता है; लेकिन मुझे नहीं लगता कि यह किस तरह के व्यवहार का कारण बनता है। उदाहरण के लिए:

[email protected]:tmp$X=PQR; echo $X | sed; X=ABC; echo $X | sed; echo $X 
PQR 
ABC 
ABC 

संपादित जोड़ने के लिए:

कुछ लोगों echo $$ का उपयोग कर पता चलता है कि चीजें हैं (या नहीं कर रहे हैं) एक subshell के कुछ हिस्सों का सुझाव दिया है। यह बिल्कुल उपयोगी नहीं है, क्योंकि $$ पैरामीटर विस्तार चरण के दौरान विस्तारित हो जाता है, जो कि किसी भी आदेश को निष्पादित करने से पहले होता है।

एक उदाहरण के रूप:

[email protected]:tmp$echo 1$$; ps; (echo 2$$; ps); echo 3$$; ps 
11194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.22 -bash 
21194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.22 -bash 
7894 ttys000 0:00.00 -bash 
31194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.22 -bash 
[email protected]:tmp$ 

आप देख सकते हैं कि ps के दूसरे मंगलाचरण पीआईडी ​​7894 के साथ, एक subshell अंदर हुआ; लेकिन echo 2$$ अभी भी मूल्य है कि चर विस्तार चरण में प्रतिस्थापित बैश, इससे पहले कि यह subshell

इसके विपरीत के लिए पैदा की दिखाता है, और प्रदर्शन है कि { .. }नहीं अंडे एक subshell करता है:

[email protected]:tmp$echo 1$$; ps; { echo 2$$; ps; }; echo 3$$; ps 
11194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.22 -bash 
21194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.22 -bash 
31194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.23 -bash 

बस साबित होता है कि @nos सही है, इसके बाद के संस्करण के लिए एक पाइप लाइन को जोड़ने:

[email protected]:tmp$echo 1$$; ps; { echo 2$$; ps; } | sed ; echo 3$$; ps 
11194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.25 -bash 
21194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.25 -bash 
7945 ttys000 0:00.00 -bash 
7946 ttys000 0:00.00 sed 
31194 
    PID TTY   TIME CMD 
1194 ttys000 0:00.25 -bash 

जैसी उम्मीद थी, खोल दो subshells, पाइप लाइन के प्रत्येक पक्ष के लिए एक spawns।

उत्तर

9

पाइपलाइन का प्रत्येक पक्ष कम से कम एक सबहेल बन जाता है।

X=PQR; echo $X; { X=ABC; echo $X; } | cat; echo $X

एक subshell /, की प्रक्रिया { X=ABC; echo $X; } और cat कम से कम कर देगा।

"पाइपलाइन में प्रत्येक कमांड को एक अलग प्रक्रिया के रूप में निष्पादित किया जाता है (यानी, सबशेल में)।" , आदमी पार्टी

से आप के बजाय करते हैं इस

X=PQR; echo $X; { X=ABC; echo $X; } ; echo | cat; echo $X

आप देखेंगे बाद में है कि echo $X एबीसी को दर्शाता है।

अन्य तरीकों से कमांड में कमांड निष्पादित किए जाते हैं, उदाहरण के लिए यदि आप एक उपसमूह पृष्ठभूमि: { X=SUB ; sleep 1; } &, वह समूह एक सबहेल में चलाएगा, जबकि केवल { X=SUB ; sleep 1; } नहीं होगा।

यदि आप कमांड में हमेशा निष्पादित आदेशों को समूहबद्ध करना चाहते हैं, तो ब्रेसिज़ के बजाय ब्रांड्स, (X=ABC ; echo $X) का उपयोग करें।

+1

मुझे लगता है कि हमारे पास विजेता है। यह '{..}' नहीं है जो सबशेल बना रहा है, यह पाइपलाइन है। मैं व्यावहारिक रूप से बाहर आया और कहा कि शुरुआत में सही है। –

+2

आपको '{', कम से कम 'bash' के मेरे संस्करण में 'के बाद एक स्थान की आवश्यकता है। – krlmlr

+1

$ (cmd args) निर्माण भी एक सबहेल बनाते हैं: 'echo $ (echo $ BASH_SUBSHELL) ' –

1

वास्तव में, ब्रेसिज़ को नए सबहेल, में निष्पादित किया जाता है, लेकिन केवल पाइप किया जाता है। पहले आदेश के बिना दूसरा, cat साथ है:

[email protected]:~$ ps; X=PQR; echo $X; { ps; X=ABC; echo $X; } | cat; ps; echo $X 
    PID TTY   TIME CMD 
6768 pts/7 00:00:00 bash 
13158 pts/7 00:00:00 ps 
PQR 
    PID TTY   TIME CMD 
6768 pts/7 00:00:00 bash 
13159 pts/7 00:00:00 bash 
13160 pts/7 00:00:00 cat 
13161 pts/7 00:00:00 ps 
ABC 
    PID TTY   TIME CMD 
6768 pts/7 00:00:00 bash 
13162 pts/7 00:00:00 ps 
PQR 
[email protected]:~$ ps; X=PQR; echo $X; { ps; X=ABC; echo $X; }; ps; echo $X 
    PID TTY   TIME CMD 
6768 pts/7 00:00:00 bash 
13239 pts/7 00:00:00 ps 
PQR 
    PID TTY   TIME CMD 
6768 pts/7 00:00:00 bash 
13240 pts/7 00:00:00 ps 
ABC 
    PID TTY   TIME CMD 
6768 pts/7 00:00:00 bash 
13245 pts/7 00:00:00 ps 
ABC 

इस मामले 6768 में टर्मिनल खोल के पीआईडी ​​है, और 13159 subshell की पीआईडी ​​ब्रेसिज़ के लिए शुरू कर दिया है।

ऐसा लगता है कि {} को उपशीर्षक में निष्पादित किया जाता है (और केवल अगर) पाइप किया जाता है।

+2

पाइप ब्रेसिज़ नहीं, सबहेल बनाता है। –

+1

नहीं, यह पाइप नहीं है, यह पाइप के संबंध में ब्रेसिज़ है। 'Ps' बनाम 'ps | के आउटपुट की जांच करें बिल्ली 'बनाम '{ps; } | cat'।। – krlmlr

+2

ब्रेसेस कभी भी एक सबहेल का आह्वान नहीं करते! केवल पाइप ही ऐसा करेंगे: http://unix.stackexchange.com/questions/127334/bash-subshell-creation-with-curly-braces – slm

संबंधित मुद्दे

 संबंधित मुद्दे