2015-12-17 5 views
12

बैश प्रक्रिया प्रतिस्थापन का उपयोग करके, मैं एक साथ फाइल पर दो अलग-अलग आदेशों को चलाने के लिए चाहता हूं। इस उदाहरण में यह आवश्यक नहीं है लेकिन कल्पना करें कि "बिल्ली/usr/share/dict/words" एक बहुत महंगा ऑपरेशन था जैसे कि 50 जीबी फ़ाइल को असम्पीड्रेस करना।बैश प्रक्रिया प्रतिस्थापन और पूंछ के साथ गलत परिणाम?

cat /usr/share/dict/words | tee >(head -1 > h.txt) >(tail -1 > t.txt) > /dev/null 

इस आदेश मैं h.txt शब्द की पहली पंक्ति को रोकने के लिए उम्मीद करेंगे दाखिल करने के बाद 'ए', और t.txt फ़ाइल "Zyzzogeton" की अंतिम पंक्ति को रोकने के लिए।

हालांकि वास्तव में क्या होता है यह है कि h.txt में "ए" होता है लेकिन t.txt में "Argillaceo" होता है जो फ़ाइल में लगभग 5% होता है।

ऐसा क्यों होता है? ऐसा लगता है कि या तो "पूंछ" प्रक्रिया जल्दी समाप्त हो रही है या धाराएं मिश्रित हो रही हैं।

इस तरह एक और इसी तरह कमान चल रहा है उम्मीद के रूप में व्यवहार:

cat /usr/share/dict/words | tee >(grep ^a > a.txt) >(grep ^z > z.txt) > /dev/null 

इस आदेश मैं a.txt सभी शब्दों है कि "एक" से शुरू होते हैं करने के लिए उम्मीद थी के बाद, जबकि z.txt के सभी शामिल हैं शब्द जो "z" से शुरू होते हैं, जो वास्तव में हुआ था।

तो यह "पूंछ" के साथ क्यों काम नहीं करता है, और यह अन्य आदेशों के साथ यह काम नहीं करेगा?

+1

मुझे लगता है कि इस http://stackoverflow.com से संबंधित है:

एक और hacky विकल्प शुरू कर तो जाने head प्रक्रिया सूची खत्म जब तक यह गैर शून्य लंबाई है नहीं से पहले t.txt को शून्य करने के लिए किया जाएगा/प्रश्न/448 9 339/बैश-प्रोसेस-प्रतिस्थापन-और-सिंकिंग जो बताती है कि बाहरी कमांड समाप्त होने पर प्रतिस्थापन निकास के साथ प्रक्रियाएं निकलती हैं, लेकिन स्पष्ट रूप से मैं यह प्रदर्शित करने में सक्षम नहीं हूं कि किसी भी आदेश के साथ वर्तमान समस्या है I मैंने अभी तक कोशिश की है –

उत्तर

10

ठीक है, क्या होने लगता है कि एक बार head -1 आदेश यह बाहर निकालता खत्म और है कि एक SIGPIPE यह नामित पाइप कि इस प्रक्रिया प्रतिस्थापन सेटअप जो एक EPIPE और भी man 2 write के अनुसार होगा उत्पन्न करने के लिए लिखने के लिए कोशिश करता है पाने के लिए tee का कारण बनता है लेखन प्रक्रिया में SIGPIPE उत्पन्न करें, जो बाहर निकलने के लिए tee का कारण बनता है और tail -1 को तुरंत बाहर निकलने के लिए मजबूर करता है, और cat बाईं ओर SIGPIPE भी मिलता है।

हम इस एक छोटे से बेहतर देख सकते हैं अगर हम head साथ प्रक्रिया करने के लिए थोड़ा और जोड़ सकते हैं और उत्पादन दोनों अधिक पूर्वानुमान और भी tee पर निर्भर रहे बिना stderr के लिए लिखा है:

for i in {1..30}; do echo "$i"; echo "$i" >&2; sleep 1; done | tee >(head -1 > h.txt; echo "Head done") >(tail -1 > t.txt) >/dev/null 

जो जब मैं चलाने यह मेरे उत्पादन दिया:

1 
Head done 
2 

तो यह लूप के सिर्फ 1 अधिक यात्रा मिल गया से पहले सब कुछ छोड़ कर चले गए हैं (हालांकि t.txt अभी भी केवल 1 है इस में)। अगर हम तो

echo "${PIPESTATUS[@]}" 

किया हम देखते हैं

141 141 

जो हम यहाँ क्या देख रहे हैं के लिए एक बहुत ही इसी तरह से SIGPIPE को this question संबंधों।

कोर्यूटिल्स रखरखावकर्ताओं ने भविष्य में पोस्टरिटी के लिए अपने tee "gotchas" पर इसे एक उदाहरण के रूप में जोड़ा है।

यह कैसे POSIX अनुपालन में फिट बैठता है आप जीएनयू संस्करण 8 की पहुंच है, तो आप http://debbugs.gnu.org/cgi/bugreport.cgi?bug=22195

पर (बंद notabug) रिपोर्ट देख सकता है के बारे में devs के साथ एक चर्चा के लिए।24 उन्होंने कुछ विकल्प जोड़े हैं (POSIX में नहीं) जो -p या --output-error=warn की तरह मदद कर सकते हैं। कि बिना आप एक जोखिम का एक सा हो जाती हैं लेकिन फँसाने और SIGPIPE की अनदेखी करके प्रश्न में वांछित कार्यक्षमता प्राप्त कर सकते हैं:

trap '' PIPE 
for i in {1..30}; do echo "$i"; echo "$i" >&2; sleep 1; done | tee >(head -1 > h.txt; echo "Head done") >(tail -1 > t.txt) >/dev/null 
trap - PIPE 

h.txt और t.txt दोनों में अपेक्षित परिणाम होगा, लेकिन अगर कुछ और है कि वांछित SIGPIPE हुआ सही तरीके से संभालने के लिए आप इस दृष्टिकोण के साथ भाग्य से बाहर होंगे।

> t.txt; for i in {1..10}; do echo "$i"; echo "$i" >&2; sleep 1; done | tee >(head -1 > h.txt; echo "Head done"; while [ ! -s t.txt ]; do sleep 1; done) >(tail -1 > t.txt; date) >/dev/null 
+1

'टीई' के लिए पॉज़िक्स-निर्दिष्ट व्यवहार यह है कि इसके पाठकों में से कोई एक बाहर निकलता है, भले ही आप कुछ विपरीत देख रहे हों, यह वास्तव में एक बग है। –

+0

"अगर किसी भी सफलतापूर्वक खोले गए फ़ाइल ऑपरेंड को लिखना विफल रहता है, तो अन्य सफलतापूर्वक खोले गए फाइल ऑपरेंड और मानक आउटपुट को लिखना जारी रहेगा, लेकिन बाहर निकलने की स्थिति शून्य-शून्य होगी। अन्यथा, उपयोगिता विवरण डिफ़ॉल्ट में निर्दिष्ट डिफ़ॉल्ट क्रियाएं लागू होती हैं।" - http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html –

+0

@ चार्ल्सडफी अच्छी तरह से उपरोक्त परिणाम पुराने संस्करण के लिए हैं, मुझे लगता है, 8.5, मैं फिर कोशिश कर सकता हूं। इसके अलावा, मैंने यह जानने के लिए पर्याप्त गहराई से नहीं पहुंचाया है कि प्रक्रिया प्रतिस्थापन एक करीबी फ़ाइल हैंडल के रूप में प्रस्तुत करता है या फिर यह प्रक्रिया समाप्त होने पर वास्तव में सिगिपी उठाती है, मुझे लगता है कि एक बग रिपोर्ट सबमिट करने से पहले मुझे और अधिक काम करना होगा, मुझे लगता है कि –

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