जब टी करने के लिए पाइपिंग की फ़ोर्स लाइन-बफ़रिंग


117

आमतौर पर, stdoutलाइन-बफ़र्ड होता है। दूसरे शब्दों में, जब तक आपका printfतर्क एक नई रेखा के साथ समाप्त हो जाता है, आप उम्मीद कर सकते हैं कि लाइन तुरन्त छपी होगी। ऐसा प्रतीत नहीं होता है कि पाइप का उपयोग करते समय इसे पुनर्निर्देशित किया जाता है tee

मेरे पास एक C ++ प्रोग्राम है, aजो स्ट्रिंग्स को आउटपुट करता है, हमेशा \n-terminated, to stdout

जब यह स्वयं ( ./a) द्वारा चलाया जाता है , तो सब कुछ सही ढंग से और सही समय पर प्रिंट होता है, जैसा कि अपेक्षित था। हालाँकि, अगर मैं इसे tee( ./a | tee output.txt) को पाइप करता हूं, तो यह तब तक कुछ भी प्रिंट नहीं करता है जब तक यह क्विट नहीं करता है, जो उपयोग करने के उद्देश्य को हरा देता है tee

मुझे पता है कि मैं इसे fflush(stdout)C ++ प्रोग्राम में प्रत्येक प्रिंटिंग ऑपरेशन के बाद जोड़कर ठीक कर सकता हूं । लेकिन क्या एक क्लीनर, आसान तरीका है? क्या कोई ऐसी आज्ञा है जिसे मैं चला सकता हूं, उदाहरण के लिए, जो stdoutपाइप का उपयोग करते समय भी लाइन-बफ़र करने के लिए मजबूर करेगी ?

जवाबों:


67

कोशिश करें unbufferजो expectपैकेज का हिस्सा है । आपके पास पहले से ही यह आपके सिस्टम पर हो सकता है।

आपके मामले में आप इसे इस तरह उपयोग करेंगे:

./a | unbuffer -p tee output.txt

( -pपाइप लाइन मोड के लिए है, जहां unbuffer स्टड से पढ़ता है और बाकी तर्कों में इसे कमांड में भेजता है)


धन्यवाद, यह काम किया, हालांकि मुझे expectखुद को संकलित करना पड़ा क्योंकि unbufferओएस एक्स में डिफ़ॉल्ट रूप से शामिल नहीं किया गया था।
houbysoft

@houbysoft: मुझे खुशी है कि इसने आपके लिए काम किया। unbufferकेवल एक छोटी सी स्क्रिप्ट है इसलिए आपको पूरे पैकेज को फिर से शुरू करने की आवश्यकता नहीं होनी चाहिए।
अगली सूचना तक रोक दिया गया।

हाँ, शायद नहीं, लेकिन ./configure && makeलगभग 10 सेकंड लगे और फिर मैं बस :) चला unbufferगया/usr/local/bin
houbysoft

3
मैंने इसे अपने मैक (10.8.5) पर काढ़ा के माध्यम से स्थापित किया: काढ़ा स्थापित होने की उम्मीद - साथ-पीसा हुआ-टीके
निल्स

2
एफडब्ल्यूआईडब्ल्यू, क्योंकि अनबफरर कुछ भ्रामक है, प्रासंगिक संरचना है unbuffer {commands with pipes/tee}
फेक नेम

128

तुम कोशिश कर सकते हो stdbuf

$ stdbuf -o 0 ./a | tee output.txt

(बड़ा) आदमी पृष्ठ का हिस्सा:

  -i, --input=MODE   adjust standard input stream buffering
  -o, --output=MODE  adjust standard output stream buffering
  -e, --error=MODE   adjust standard error stream buffering

If MODE is 'L' the corresponding stream will be line buffered.
This option is invalid with standard input.

If MODE is '0' the corresponding stream will be unbuffered.

Otherwise MODE is a number which may be followed by one of the following:
KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.
In this case the corresponding stream will be fully buffered with the buffer
size set to MODE bytes.

इसे ध्यान में रखें, हालांकि:

NOTE: If COMMAND adjusts the buffering of its standard streams ('tee' does
for e.g.) then that will override corresponding settings changed by 'stdbuf'.
Also some filters (like 'dd' and 'cat' etc.) dont use streams for I/O,
and are thus unaffected by 'stdbuf' settings.

आप नहीं चला रहे हैं stdbufपर tee, आप उस पर चला रहे हैं a, तो यह आप प्रभावित नहीं होना चाहिए, जब तक आप की प्रतिरोधक सेट a'में रों धाराओं aरों स्रोत'।

इसके अलावा, stdbufहै POSIX, लेकिन जीएनयू-coreutils का हिस्सा है।


3
धन्यवाद, लेकिन यह ओएस एक्स पर उपलब्ध नहीं लगता है (प्रश्न को ओएक्सएक्स-लॉयन टैग किया गया है)।
2

2
@houbysoft - मुझे पूरा यकीन है कि GNU टूल्स OS X पर स्थापित किए जा सकते हैं
jordanm

1
@ जोर्डनम: शायद, लेकिन पूरे जीएनयू टूल्स को इस तरह स्थापित करना इसके लिए ओवरकिल जैसा लगता है ...
houbysoft

1
यह उत्तर अपग्रेड किया गया है क्योंकि stdbufहम पहले से ही उपयोग किए जा रहे Centos Linux वितरण पर उपलब्ध हैं, और unbufferऐसा नहीं है। धन्यवाद!
ह्यू वाल्टर्स

6
अजगर स्क्रिप्ट के लिए stdbuf काम नहीं करेगा, लेकिन आप -uअजगर के पक्ष में बफ़रिंग को अक्षम करने के लिए उपयोग कर सकते हैं :python3 -u a.py | tee output.txt
Honza

27

आप कमांड का उपयोग करके छद्म टर्मिनल में अपनी कमांड को निष्पादित करने का भी प्रयास कर सकते हैं script(जो पाइप पर लाइन-बफ़र्ड आउटपुट लागू करना चाहिए)!

script -q /dev/null ./a | tee output.txt     # Mac OS X, FreeBSD
script -c "./a" /dev/null | tee output.txt   # Linux

ध्यान रखें कि scriptकमांड लिपटे कमांड के बाहर निकलने की स्थिति का प्रचार नहीं करता है।


3
script -t 1 /path/to/outputfile.txt ./aमेरे उपयोग के मामले के लिए बहुत अच्छा काम किया। यह सभी आउटपुट को लाइव स्ट्रीम करता है outputfile.txtजबकि इसे आपके शेल के स्टडआउट पर प्रिंट भी करता है। उपयोग करने की आवश्यकता नहीं थीtee
पीटर बर्ग

26

आप stdio.h से सेटलाइनब्यूफ का उपयोग कर सकते हैं।

setlinebuf(stdout);

यह बफरिंग को "लाइन बफर" में बदलना चाहिए।

यदि आपको अधिक लचीलेपन की आवश्यकता है, तो आप सेट्वुफ का उपयोग कर सकते हैं।


8
मुझे आश्चर्य है कि इस समाधान में इतने अधिक बदलाव क्यों हैं। यह एकमात्र उपाय है जो कॉलर पर बोझ नहीं डालता है।
ऑक्सीजिन

1
ध्यान दें कि यह मानक C (या यहां तक ​​कि POSIX) नहीं है। यह संभवतः उपयोग करने के लिए बेहतर है setvbuf(stdout, NULL, _IOLBF, 0), जो बिल्कुल बराबर है।
rvighne

इसने C ++ प्रोग्राम के साथ OS X कैटालिना पर मेरा मुद्दा तय किया जो प्रिंटफ () आईएनजी था और मैं टी को पाइप कर रहा था, लेकिन केवल आउटपुट देख रहा था जब प्रोग्राम समाप्त हो गया था।
jbaxter

2

आप के बजाय सी ++ धारा कक्षाओं का उपयोग करते हैं, हर std::endl है एक अंतर्निहित फ्लश। सी-स्टाइल प्रिंटिंग का उपयोग करना, मुझे लगता है कि आपके द्वारा सुझाई गई विधि ( fflush()) एकमात्र तरीका है।


4
दुर्भाग्य से यह सच नहीं है। आप समान व्यवहार का अवलोकन c ++ std :: cout के साथ भी कर सकते हैं जब std :: endl या std :: flush का उपयोग कर रहे हों। बफ़रिंग शीर्ष पर होती है और लिनक्स में सबसे आसान समाधान सेटलाइनब्यूफ़ (स्टडआउट) लगता है; मुख्य कोड में पहली पंक्ति के रूप में () जब आप प्रोग्राम के लेखक हैं और स्रोत कोड को बदलने में सक्षम नहीं होने पर अन्य उपरोक्त समाधानों का उपयोग कर रहे हैं।
ऑक्सीजिन

1
@oxygene यह सच नहीं है। मैंने इसे आजमाया और टीईएल को पाइप करने पर बफर को फ्लश करता है (प्रिंटफ के विपरीत)। कोड: #include <iostream> #include <unistd.h> int main(void) { std::cout << "1" << std::endl; sleep(1); std::cout << "2" << std::endl; }। एंडल हमेशा बफर को फ्लश करता है जैसा कि यहां परिभाषित किया गया है: en.cppreference.com/w/cpp/io/manip/endl
कर्टिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.