इस विशेष मामले में, आपके पास पाइपलाइन में exec
है। पाइपलाइन कमांड की श्रृंखला को निष्पादित करने के लिए, खोल को प्रारंभिक रूप से कांटा बनाना चाहिए, जिससे उप-खोल हो। (विशेष रूप से इसे पाइप, फिर कांटा बनाना है, ताकि पाइप के "बाईं ओर" चलने वाली सभी चीज़ों को पाइप के "दाईं ओर" जो भी हो, उसका आउटपुट भेजा जा सके।)
यह देखने के लिए तथ्य यह है क्या हो रहा है में है, की तुलना:
साथ
{ ls; echo this too; } | cat
:
{ exec ls; echo this too; } | cat
पूर्व रन ls
उप खोल से बाहर निकले बिना, ताकि इस उप-खोल इसलिए अभी भी चारों ओर echo
चलाने के लिए है । उत्तरार्द्ध उप-शेल छोड़कर ls
चलाता है, जो अब echo
करने के लिए नहीं है, और this too
मुद्रित नहीं है।
(घुंघराले-ब्रेसिज़ { cmd1; cmd2; }
के उपयोग के सामान्य रूप से उप खोल कांटा कार्रवाई है कि आप कोष्ठकों (cmd1; cmd2)
साथ मिल को दबा है, लेकिन एक पाइप के मामले में, कांटा "मजबूर" है, क्योंकि यह थे।)
वर्तमान खोल का पुनर्निर्देशन केवल तभी होता है जब exec
शब्द के बाद "चलाने के लिए कुछ नहीं" होता है। इस प्रकार, उदाहरण के लिए, exec >stdout 4<input 5>>append
वर्तमान खोल को संशोधित करता है, लेकिन exec foo >stdout 4<input 5>>append
निष्पादन आदेश foo
करने का प्रयास करता है। [नोट: यह कड़ाई से सटीक नहीं है; परिशिष्ट देखें।]
दिलचस्प है, एक इंटरैक्टिव खोल में, के बाद exec foo >output
विफल रहता है कोई आदेश foo
, चारों ओर खोल लाठी है वहाँ क्योंकि, लेकिन stdout output
दायर करने के लिए निर्देशित कर दिये रहता है। @ Pumbaa80 को टोपी के एक टिप के साथ (आप exec >/dev/tty
साथ ठीक हो सकता है एक स्क्रिप्ट में, exec foo
की विफलता स्क्रिप्ट समाप्त हो जाता है।।)
, यहाँ कुछ और भी उदाहरण है:
#! /bin/bash
shopt -s execfail
exec ls | cat -E
echo this goes to stdout
echo this goes to stderr 1>&2
(ध्यान दें: cat -E
मेरे सामान्य cat -vET
से नीचे सरलीकृत किया गया है, जो कि "मुझे पहचानने योग्य तरीके से गैर-प्रिंटिंग वर्ण देखने दें" के लिए मेरा आसान तरीका है)। जब यह स्क्रिप्ट चलती है, ls
से आउटपुट cat -E
लागू होता है (लिनक्स पर यह $ 200 के रूप में दिखाई देने वाली अंतराल को बनाता है), लेकिन स्टडआउट और स्टेडर (शेष दो पंक्तियों पर) को भेजा गया आउटपुट पुनर्निर्देशित नहीं है । | cat -E
से > out
बदलें और, स्क्रिप्ट चलाने के बाद, फ़ाइल out
की सामग्री का निरीक्षण करें: अंतिम दो echo
एस वहां नहीं हैं।
अब ls
से foo
(या कुछ अन्य आदेश जो नहीं मिलेगा) को बदलें और स्क्रिप्ट को फिर से चलाएं। इस बार उत्पादन होता है:
$ ./demo.sh
./demo.sh: line 3: exec: foo: not found
this goes to stderr
और फ़ाइल out
अब पहले echo
लाइन द्वारा उत्पादित सामग्री है।
यह exec
"वास्तव में करता है" जितना संभव हो उतना स्पष्ट (लेकिन अधिक स्पष्ट नहीं है, क्योंकि अल्बर्ट आइंस्टीन ने इसे नहीं रखा :-))।
आम तौर पर, जब खोल "सरल कमांड" निष्पादित करने के लिए चला जाता है (सटीक परिभाषा के लिए मैन्युअल पृष्ठ देखें, लेकिन यह विशेष रूप से "पाइपलाइन" में कमांड को बहिष्कृत करता है), यह किसी भी I/O पुनर्निर्देशन संचालन को निर्दिष्ट करता है <
, >
, और इसलिए आवश्यक फ़ाइलों को खोलकर। फिर खोल fork
(या कुछ समकक्ष लेकिन अधिक कुशल संस्करण जैसे vfork
या clone
अंतर्निहित ओएस, कॉन्फ़िगरेशन इत्यादि के आधार पर), और, बाल प्रक्रिया में, खुली फ़ाइल डिस्क्रिप्टर (dup2
कॉल या समकक्ष का उपयोग करके) को पुन: व्यवस्थित करता है। वांछित अंतिम व्यवस्था: > out
खुला वर्णनकर्ता चाल एफडी 1-stdout-जबकि 6> out
एफडी 6.
आप exec
कीवर्ड, हालांकि, खोल को दबा fork
कदम निर्दिष्ट करते हैं खुला वर्णनकर्ता ले जाता है। यह सभी फाइल खोलने और फ़ाइल-डिस्क्रिप्टर-सामान्य रूप से पुनर्व्यवस्थित करता है, लेकिन इस बार, यह किसी भी और सभी बाद के आदेश को प्रभावित करता है। अंत में, सभी पुनर्निर्देशन करने के बाद, शेल execve()
(सिस्टम-कॉल भावना में) आदेश देता है, यदि कोई है तो आदेश।यदि कोई आदेश नहीं है, या execve()
कॉल और विफल रहता है तो खोल चलाना जारी रहता है (इंटरैक्टिव है या आपने execfail
सेट किया है), शैल सैनिकों पर। यदि execve()
सफल होता है, तो शेल अब मौजूद नहीं है, जिसे नए कमांड द्वारा प्रतिस्थापित किया गया है। यदि execfail
अनसेट है और खोल इंटरैक्टिव नहीं है, तो खोल निकलता है।
(वहाँ भी command_not_found_handle
खोल समारोह का जोड़ा जटिलता है: बैश के exec
इसे चलाने को दबाने के लिए परीक्षण के परिणाम के आधार पर, लगता है सामान्य रूप में exec
कीवर्ड, बनाता खोल अपनी ही काम करता है, यानी पर नहीं लग रही है यदि आप एक है। खोल समारोह च, f
एक साधारण आदेश के रूप में चल खोल समारोह चलाता है, (f)
जो इसे एक उप खोल में चलाता है, लेकिन इस पर (exec f)
स्किप के चल रहा है के रूप में।)
क्यों
ls>out1 ls>out2
दो फ़ाइलें (के साथ या एक के बिना बनाता है के रूप में
exec
), यह काफी आसान है: खोल प्रत्येक पुनर्निर्देशन को खोलता है, और फिर फ़ाइल वर्णनकर्ताओं को स्थानांतरित करने के लिए
dup2
का उपयोग करता है। यदि आपके पास दो सामान्य
>
रीडायरेक्ट हैं, तो खोल दोनों खुलता है, पहले को एफडी 1 (stdout) में ले जाता है, फिर दूसरे को एफडी 1 (फिर से स्टडआउट) में ले जाता है, प्रक्रिया में पहले बंद कर देता है। अंत में, यह
ls ls
चलाता है, क्योंकि
>out1 >out2
को हटाने के बाद यह शेष है। जब तक
ls
नाम की कोई फ़ाइल नहीं है,
ls
कमांड stderr की शिकायत करता है, और stdout के लिए कुछ भी नहीं लिखता है।
मैंने कुछ सीखा! – blueshift
आप 'exec' पर लिंक सी 'exec' फ़ंक्शन है। आप जो परीक्षण कर रहे हैं वह 'bash'' exec' buildin है। वे एक जैसे नहीं हैं। Www.gnu.org/software/bash/manual/bashref.html –
@ जे -16 एसडीआईजेड को सुझाए गए अनुसार सही किया गया है, लेकिन समस्या – artaxerxe