अर्ध-एसिंक्रोनस पाइप


11

मान लें कि मेरे पास निम्नलिखित पाइप है:

a | b | c | d

मैं कैसे पूरा करने के लिए इंतजार कर सकते हैं c(या b) में shया bash? इसका मतलब है कि स्क्रिप्ट dकिसी भी समय शुरू हो सकती है (और इसके लिए प्रतीक्षा करने की आवश्यकता नहीं है) लेकिन cसही तरीके से काम करने के लिए पूर्ण आउटपुट की आवश्यकता होती है।

उपयोग के मामले में है difftoolके लिए gitहै कि छवियों तुलना करती है। इसे gitइसके इनपुट ( a | b | cभाग) को संसाधित करने और तुलना ( dभाग) के परिणामों को प्रदर्शित करने की आवश्यकता है । फोन करने वाले इनपुट कि के लिए आवश्यक है को नष्ट करेगा aऔर b। इसका मतलब यह है कि स्क्रिप्ट से लौटने से पहले, प्रक्रिया c(या b) को समाप्त करना होगा। दूसरी ओर, मैं इंतजार नहीं कर सकता dक्योंकि इसका मतलब है कि मैं उपयोगकर्ता इनपुट की प्रतीक्षा कर रहा हूं।

मुझे पता है कि मैं cएक अस्थायी फ़ाइल के परिणाम लिख सकता हूं , या शायद एक फीफो का उपयोग कर सकता हूं bash। (निश्चित नहीं कि अगर फीफो मदद करेगा, हालांकि।) क्या यह संभव है बिना अस्थायी फाइलों के इसे हासिल करना sh?

संपादित करें

शायद यह पर्याप्त होगा अगर मैं एक विश्वसनीय फैशन में प्रक्रिया c(या b) की प्रक्रिया आईडी का पता लगा सकता हूं । तब पूरे पाइप को एसिंक्रोनस रूप से शुरू किया जा सकता था, और मैं एक प्रक्रिया आईडी की प्रतीक्षा कर सकता था। की तर्ज पर कुछ

wait $(a | b | { c & [print PID of c] ; } | d)

संपादित करें ^ 2

मुझे एक समाधान मिला है, टिप्पणियाँ (या अभी भी बेहतर समाधान) का स्वागत है।


आपका मतलब है कि आप पूरा होने के बाद ही dप्रोसेसिंग शुरू करना चाहते हैं ? जैसा कि यह आता है आप प्रत्येक आउटपुट लाइन को संसाधित करना शुरू नहीं करना चाहते हैं ? ccd
terdon

@terdon: नहीं, dजब भी यह पसंद करने के लिए शुरू करने के लिए स्वतंत्र है, लेकिन cइससे पहले कि मैं आगे बढ़ सकता हूं समाप्त करने की आवश्यकता है।
krlmlr

यह आत्म-विरोधाभासी प्रतीत होता है, अगर dयह पसंद होने पर शुरू हो सकता है, तो वास्तव में आप किसका इंतजार कर रहे हैं?
terdon

@terdon: उपयोग मामला दिखाने के लिए विस्तारित किया गया।
krlmlr

यदि dआउटपुट का उपयोग नहीं करता है, cतो dपाइपलाइन का हिस्सा बनाने के लिए कोई मतलब नहीं है । लेकिन यदि आप dइनपुट का उपयोग करते हैं तो dअपने इनपुट पर कुछ समय के लिए काम करना चाहिए, इसके बाद आपके दृष्टिकोण के लिए यह सब पढ़कर कोई फर्क नहीं पड़ता है।
हौके लैजिंग

जवाबों:


6
a | b | { c; [notify];} | d

अधिसूचना एक पीआईडी ​​को एक संकेत द्वारा उदाहरण के लिए किया जा सकता है जिसे पर्यावरण चर ( kill -USR1 $EXTPID) में या फ़ाइल ( touch /path/to/file) बनाकर पारित किया गया है ।

एक अन्य विचार:

आप पाइपलाइन से अगली प्रक्रिया को निष्पादित करते हैं (जिसे आप शुरू करने के लिए इंतजार कर रहे हैं):

a | b | { c; exec >&-; nextprocess;} | d

या

a | b | { c; exec >&-; nextprocess &} | d

धन्यवाद। लेकिन फिर, मध्यवर्ती आउटपुट के लिए एक अस्थायी फ़ाइल बनाना अधिक क्रिया और पार्स (एक मानव के लिए) के लिए आसान है। इसके अलावा, मैं संकेत के साथ दौड़ की स्थिति से कैसे बचूं? ... मैं एक क्लीनर समाधान की उम्मीद कर रहा था, लेकिन अगर यह जाने का रास्ता है, तो ऐसा ही हो।
krlmlr

@krlmlr क्या दौड़ हालत?
हौके लैजिंग

notifyइससे पहले कि मैं सिग्नल ट्रैप सेट करता, निष्पादित किया जा सकता था। मैं यह कैसे सुनिश्चित कर सकता हूं कि उस संकेत को याद न करें?
13:25 बजे krlmlr

@krlmlr आप स्क्रिप्ट को रोकते हैं जो पाइपलाइन को तब तक कॉल करती है जब तक कि वह एक सिग्नल प्राप्त न कर ले जो trapपरिभाषित होने के बाद भेजा जाता है।
हौके लैजिंग

आपका संपादन: पाइप को लूप में कहा जाता है, जिस पर मेरा कोई नियंत्रण नहीं है। दुर्भाग्य से, { c; bg; }या { c; exit 0; }काम करने के लिए प्रतीत नहीं होता है।
krlmlr

5

अगर मैं आपके सवाल को सही ढंग से समझूं, तो यह काम करना चाहिए:

a | b | c | { (exec <&3 3<&-; d) &} 3<&0

(fd 3 ट्रिक इसलिए है क्योंकि कुछ (अधिकांश) गोले रीडायरेक्ट स्टड को / dev / null के साथ रीडायरेक्ट करते हैं &)।


4

बैश में, आप एक प्रक्रिया प्रतिस्थापन का उपयोग कर सकते हैं । प्रक्रिया प्रतिस्थापन में कमांड एसिंक्रोनस रूप से चलती है, इसके लिए प्रतीक्षा नहीं की जाती है।

a | b | c > >(d)

धन्यवाद। यह bashकेवल, सही है - कोई shसमर्थन नहीं ?
krlmlr

@krlmlr बैश / zsh केवल (और कुछ संशोधनों के साथ ksh93)।
गिल्स एसओ- बुराई को रोकना '

3

यह मैंने ट्रायल और त्रुटि से पाया है, हाउक के इनपुट की मदद से:

a | b | { c; kill -PIPE $$; } | d

इसके तुल्य:

a | b | ( c; kill -PIPE $$; ) | d

(उत्तरार्द्ध अधिक स्पष्ट है, क्योंकि {}अगर एक पाइप के अंदर एक उप-प्रकार में चलेगा।)

कुछ अन्य संकेत (सहित QUIT, TERMऔर USR1) काम करते हैं, हालांकि, इस मामले में संकेत का विवरण टर्मिनल पर दिखाया गया है।

मुझे आश्चर्य है कि यह PIPEसंकेत का मूल उद्देश्य है । मैनुअल के अनुसार :

SIGPIPE: PIPEसिग्नल को एक प्रक्रिया के लिए भेजा जाता है जब वह दूसरे छोर से जुड़ी प्रक्रिया के बिना एक पाइप पर लिखने का प्रयास करता है।

इसका मतलब यह है कि जब मैं कृत्रिम रूप से उपखंड में एक पाइप सिग्नल भेजता हूं, तो यह चुपचाप समाप्त हो जाता है, अंतिम उपभोक्ता ( d) को अकेला छोड़ देता है।

यह shऔर दोनों में काम करता है bash


0

आप spongeप्रोग्राम को "अधिक जानकारी" पैकेज से उपयोग कर सकते हैं :

a | b | c | sponge | d

स्पंज को cपाइप करने से पहले उसके आउटपुट के अंत के लिए होगा d। आशा है कि तुम क्या चाहते थे।


0

आप बस कर सकते हैं:

a | b | c | (d ; cat > /dev/null)

इसलिए, जब dखत्म catहो जाएगा , तब cतक बाकी के आउटपुट को अवशोषित कर लेगा ।

ठीक है। टिप्पणियों के बाद, मुझे लगता है कि जवाब सीधे dपृष्ठभूमि में शुरू करना है।

करना:

a | b | c | (d &)

या का उपयोग स्टीफ़न Chazelas के समाधान अगर वहाँ के साथ समस्याएं हैं dसे पढ़ने stdin


मुझे डर है कि मेरा उपयोग मामला बल्कि अन्य तरह से गोल है: cपहले की तुलना में खत्म हो गया है d, और मुझे cखत्म होने तक इंतजार करना होगा लेकिन परवाह नहीं है d
19

क्षमा करें, मुझे नहीं मिला। जब आप cखत्म करना चाहते हैं और dअभी भी चल रहे हैं तो आप क्या करना चाहते हैं ? मार डाला d?
एंगस

dएक GUI है और जब तक उपयोगकर्ता इसे बंद नहीं कर सकता।
krlmlr

ठीक है ... लेकिन यह पहले से ही होता है। जब a, bऔर cअपना काम पूरा करते हैं, तो वे स्टडआउट और बाहर निकल जाते हैं; और केवल dभाग रहा है। क्या आप खत्म होने dपर पृष्ठभूमि में भेजना चाहते हैं c? क्या यही है?
कोण

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