एक सतत स्ट्रीम 'grep' कैसे करें?


729

क्या grepएक सतत धारा पर उपयोग संभव है ?

मेरा मतलब है कि एक tail -f <file>कमांड की तरह है , लेकिन grepआउटपुट पर केवल मेरी रुचि रखने वाली लाइनों को रखने के लिए।

मैंने कोशिश की है, tail -f <file> | grep patternलेकिन ऐसा लगता है कि grepकेवल एक बार tailखत्म होने के बाद ही निष्पादित किया जा सकता है , ऐसा कभी नहीं कहना है।


9
यह अत्यधिक संभावना है कि फ़ाइल बनाने वाला प्रोग्राम अपने आउटपुट को फ्लश नहीं कर रहा है।
स्टीव-ओ

tail -f fileकार्य करता है (मैं वास्तविक समय में नया आउटपुट देखता हूं)
Matthieu Napoli


@ वास्तव में, उस के बारे में नहीं सोचा
Matthieu Napoli

हो सकता है कि आपके इनपुट स्ट्रीम में कोई नई लाइनें न हों? यदि ऐसा है तो grep आगे नहीं बढ़ेगा।
लिंच

जवाबों:


1326

grepBSD grep (FreeBSD, Mac OS X आदि) का उपयोग करते समय लाइन के बफरिंग मोड को चालू करें ।

tail -f file | grep --line-buffered my_pattern

आपको GNU grep के लिए ऐसा करने की आवश्यकता नहीं है (बहुत अधिक लिनक्स पर उपयोग किया जाता है) क्योंकि यह डिफ़ॉल्ट रूप से फ्लश करेगा (YMMV अन्य Unix-पसंद जैसे कि SmartOS, AIX या QNX के लिए)।


3
@MichaelNiemand आप पूंछ -F फ़ाइल का उपयोग कर सकते हैं | grep - लाइन-बफ़र्ड my_pattern
jcfrei

47
@MichaelGoldshteyn यह आसान ले लो। लोग इसे अपवित्र करते हैं क्योंकि वे इस पृष्ठ को तब ढूंढते हैं जब वे "grep लाइन बफ़र" करते हैं और यह उनके लिए एक समस्या का हल करता है जो प्रश्न के रूप में वास्तव में सामने नहीं आ सकता है।
Raine

4
मैं यहाँ के उत्पादन grep की कोशिश कर रहा था strace। इसके बिना --line-buffered, यह काम नहीं करेगा।
साजा

5
@MichaelGoldshteyn (और उनकी टिप्पणी के upvoters): मुझे हमेशा यह समस्या रही है tail -f | grep, और --line-bufferedयह मेरे लिए (Ubuntu 14.04, GNU grep संस्करण 2.16 पर) हल करता है। "स्टडआउट एक ट्टी है" लॉजिक लागू होने पर "उपयोग लाइन बफरिंग कहाँ है?" में git.savannah.gnu.org/cgit/grep.git/tree/src/grep.c , line_bufferedकेवल तर्क पार्सर द्वारा निर्धारित है।
अनसमुंड एल्डहुसेट

8
@MichaelGoldshteyn मैं macOS पर BSD grep का उपयोग कर रहा हूं और इसके बिना --line-bufferedमुझे कोई आउटपुट नहीं मिलता है। हालाँकि, परीक्षण के बाद, यह ऐसा दिखता है जैसे GNU grep क्या वर्णन करता है। इसलिए ज्यादातर चीजें यूनिक्स की तरह, यह आपके प्लेटफॉर्म के कार्यान्वयन पर निर्भर करती हैं। चूंकि प्रश्न ने प्लेटफ़ॉर्म निर्दिष्ट नहीं किया था, इसलिए आपकी जानकारी गलत प्रतीत होती है - बीएसडी grep के लिए कोड की समीक्षा करने और इसे GNU grep से तुलना करने के बाद, व्यवहार निश्चित रूप से --line-बफर विकल्प द्वारा नियंत्रित होता है। यह सिर्फ इतना है कि केवल जीएनयू जीआरई डिफ़ॉल्ट रूप से फ्लश करता है।
रिचर्ड वेट

118

मैं tail -f <file> | grep <pattern>हर समय उपयोग करता हूं ।

यह grep फ्लश तक इंतजार करेगा, तब तक नहीं जब तक यह खत्म नहीं होता (मैं Ubuntu का उपयोग कर रहा हूं)।


4
जो काफी समय तक चल सकता है, इसलिए कोशिश करें कि अधीर न हों।
glglgl

इसमें लगभग कितना समय लग सकता है?
Matthieu Napoli

@ मैथ्यू: मुख्य रूप से इस बात पर निर्भर करता है कि आप किस चीज के लिए तैयार हैं, और आपके ओएस पर बफ़र्स कितने बड़े हैं। अगर ग्रीप हर कुछ घंटों में केवल एक छोटी स्ट्रिंग से मेल खाता है, तो यह पहले फ्लश के दिन होगा।
13

13
टेल आउटपुट बफरिंग का उपयोग नहीं करता है - grep करता है।
XzKto

7
नहीं, grep आउटपुट बफरिंग नहीं करता है जब आउटपुट एक tty डिवाइस पर जा रहा है, जैसा कि स्पष्ट रूप से इस उत्तर में है। यह लाइन बफरिंग करता है! यह सही उत्तर है और स्वीकृत उत्तर होना चाहिए। अधिक विवरण के लिए वर्तमान में स्वीकृत ( गलत ) उत्तर के लिए मेरी लंबी टिप्पणी देखें।
माइकल गोल्डस्मिन

67

मुझे लगता है कि आपकी समस्या यह है कि grep कुछ आउटपुट बफरिंग का उपयोग करता है। प्रयत्न

tail -f file | stdbuf -o0 grep my_pattern

यह grep के आउटपुट बफ़रिंग मोड को असंबद्ध में सेट करेगा।


7
और इसका फायदा यह है कि इसका उपयोग इसके अलावा कई अन्य कमांड के लिए भी किया जा सकता है grep
पीटर वी। मॉर्च

4
हालांकि, जैसा कि मैंने इसके साथ और अधिक खेलने के बाद पता लगाया है, कुछ आदेश केवल अपने उत्पादन को फ्लश करते हैं जब एक ट्टी से जुड़ा होता है, और उसके लिए, unbuffer( expect-devडेबियन पर पैकेज में) राजा है । तो मैं stdbuf पर unbuffer का उपयोग करेंगे।
पीटर वी। मॉरच

5
@Peter V. Mørch हाँ, आप सही हैं, अनबफ़र कभी-कभी काम कर सकता है जहाँ stdbuf नहीं कर सकता। लेकिन मुझे लगता है कि आप एक 'जादू' प्रोग्राम खोजने की कोशिश कर रहे हैं जो आपकी समस्या को समझने के बजाय हमेशा आपकी समस्याओं को ठीक करेगा। वर्चुअल ट्टी बनाना असंबंधित कार्य है। Stdbuf वास्तव में वही करता है जो हम चाहते हैं (मान देने के लिए मानक आउटपुट बफर सेट करता है), जबकि unbuffer बहुत सारे छिपे हुए सामान करता है जो हम नहीं चाहते हैं ( topstdbuf और unbuffer के साथ इंटरैक्टिव तुलना करें )। और वास्तव में कोई 'जादू' समाधान नहीं है: अनबफरर कभी-कभी विफल भी हो जाता है, उदाहरण के लिए awk अलग-अलग बफर कार्यान्वयन का उपयोग करता है (stdbuf भी विफल हो जाएगा)।
XzKto

2
"लेकिन मुझे लगता है कि आप एक 'जादू' प्रोग्राम खोजने की कोशिश कर रहे हैं जो आपकी समस्या को समझने के बजाय हमेशा आपकी समस्याओं को ठीक करेगा।" - मुझे लगता है कि आप सही हैं! ;-)
पीटर वी। मॉर्क

1
के बारे में कुछ और जानकारी stdbuf, ` अनबफ़र
Tor Klingberg

13

यदि आप पूरी फ़ाइल (केवल पूंछ नहीं) में मैच ढूंढना चाहते हैं , और आप चाहते हैं कि यह किसी भी नए मैच के लिए बैठे और इंतजार करे, तो यह अच्छी तरह से काम करता है:

tail -c +0 -f <file> | grep --line-buffered <pattern>

-c +0ध्वज का कहना है कि उत्पादन शुरू कर देना चाहिए 0बाइट ( -c) शुरुआत में (से +फ़ाइल की)।


12

ज्यादातर मामलों में, आप कर सकते हैं tail -f /var/log/some.log |grep fooऔर यह ठीक काम करेगा।

यदि आपको रनिंग लॉग फ़ाइल पर कई greps का उपयोग करने की आवश्यकता है और आप पाते हैं कि आपको कोई आउटपुट नहीं मिलता है, तो आपको --line-bufferedस्विच को अपने मध्य grep (s) में रखने की आवश्यकता हो सकती है , जैसे:

tail -f /var/log/some.log | grep --line-buffered foo | grep bar

7

आप इस उत्तर को वृद्धि के रूप में मान सकते हैं .. आमतौर पर मैं उपयोग कर रहा हूं

tail -F <fileName> | grep --line-buffered  <pattern> -A 3 -B 5

फ़ाइल घुमाने के मामले में -F बेहतर है (यदि फ़ाइल घुमाया गया तो ठीक से काम नहीं करेगा)

-ए -बी पैटर्न घटित होने से ठीक पहले और बाद में लाइनों को प्राप्त करने के लिए उपयोगी है .. ये ब्लॉक धराशायी लाइन विभाजकों के बीच दिखाई देंगे

लेकिन मेरे लिए मैं निम्नलिखित करना पसंद करता हूं

tail -F <file> | less

यदि आप स्ट्रीम किए गए लॉग के अंदर खोजना चाहते हैं तो यह बहुत उपयोगी है। मेरा मतलब है कि आगे और पीछे जाएं और गहराई से देखें


4
grep -C 3 <pattern>, के स्थान पर-ए <एन> और-बी <एन> अगर एन समान है।
एकेएस

6

किसी को भी इसके लिए मेरे सामान्य रूप से जाने की पेशकश नहीं देखी:

less +F <file>
ctrl + c
/<search term>
<enter>
shift + f

मैं इसे पसंद करता हूं, क्योंकि ctrl + cजब भी आप फ़ाइल के माध्यम से रोकना और नेविगेट करने के लिए उपयोग कर सकते हैं , और फिर shift + fलाइव, स्ट्रीमिंग खोज पर वापस जाने के लिए हिट कर सकते हैं।


4

sed एक बेहतर विकल्प होगा ( धारा संपादक)

tail -n0 -f <file> | sed -n '/search string/p'

और फिर यदि आप चाहते थे कि एक विशेष स्ट्रिंग मिलने के बाद आप टेल कमांड से बाहर निकलें:

tail --pid=$(($BASHPID+1)) -n0 -f <file> | sed -n '/search string/{p; q}'

स्पष्ट रूप से एक बशीवाद: $ BASHPID टेल कमांड की प्रोसेस आईडी होगी। पाइप में पूंछ के बाद sed कमांड अगले है, इसलिए sed प्रक्रिया आईडी $ BASHPID + 1 होगी।


1
यह धारणा कि सिस्टम पर अगली प्रक्रिया शुरू हुई है ( $BASHPID+1) आपकी होगी कई स्थितियों में झूठी है, और यह बफरिंग समस्या को हल करने के लिए कुछ भी नहीं करता है जो संभवतः ओपी के बारे में पूछने की कोशिश कर रहा था। विशेष रूप से, यहाँ sedपर सिफारिश करना grepकेवल (संदिग्ध) वरीयता का मामला लगता है। ( यदि आप उस बिंदु के p;qसाथ व्यवहार कर सकते हैं, grep -m 1जिसे आप देने का प्रयास कर रहे हैं।)
tripleee

काम करता है, sed कमांड प्रत्येक लाइनों को प्रिंट करता है जैसे ही तैयार होता है, grep कमांड के साथ --line-bufferedनहीं। मैं ईमानदारी से माइनस 1 को नहीं समझता
MUY बेल्जियम

यह स्थापित है कि बफ़रिंग grep के साथ समस्या है । Sed का उपयोग करते हुए लाइन बफरिंग को संभालने के लिए कोई विशेष कार्रवाई की आवश्यकता नहीं है , यह डिफ़ॉल्ट व्यवहार है, इसलिए शब्द स्ट्रीम का मेरा जोर है । और सच है, कोई गारंटी नहीं है $ BASHPID + 1 का पालन करने के लिए सही पीआईडी होगी, लेकिन चूंकि पीआईडी ​​आवंटन अनुक्रमिक है और पाइप्ड कमांड को तुरंत एक पीआईडी सौंपा गया है, यह पूरी तरह से संभावित है।
क्रिश्चियन हरे

1

हां, यह वास्तव में ठीक काम करेगा। Grepऔर अधिकांश यूनिक्स कमांड एक समय में एक ही स्ट्रीम पर काम करते हैं। प्रत्येक पंक्ति जो पूंछ से निकलती है, उसका विश्लेषण किया जाएगा और यदि यह मेल खाता है तो इसे पारित किया जाएगा।


2
यह वास्तव में सही नहीं है। यदि grepपाइप श्रृंखला में अंतिम कमांड है, तो यह आपके समझाने के अनुसार कार्य करेगा। हालाँकि, अगर यह बीच में है तो यह एक समय में लगभग 8k आउटपुट को बफर कर देगा।
महमूद अल-कुद्सी

1

यह एक आदेश मेरे लिए काम करता है (सुसे):

mail-srv:/var/log # tail -f /var/log/mail.info |grep --line-buffered LOGIN  >> logins_to_mail

मेल सेवा के लिए लॉगिन एकत्रित करना


-1

आप निश्चित रूप से सफल नहीं होंगे

tail -f /var/log/foo.log |grep --line-buffered string2search

जब आप पूंछ के लिए एक उपनाम के रूप में "कॉलोर्टेल" का उपयोग करते हैं, जैसे। बाश में

alias tail='colortail -n 30'

यदि आप इस प्रकार के अन्य उपनामों से जांच कर सकते हैं कि यह पूंछ के अन्य उपनाम जैसा है colortail -n 30। तो आप अपने अपराधी है :)

समाधान:

के साथ उपनाम हटा दें

unalias tail

सुनिश्चित करें कि आप इस कमांड द्वारा 'वास्तविक' टेल बाइनरी का उपयोग कर रहे हैं

type tail

जो कुछ इस तरह उत्पादन करना चाहिए:

tail is /usr/bin/tail

और फिर आप अपनी कमांड चला सकते हैं

tail -f foo.log |grep --line-buffered something

सौभाग्य।


-4

जहाँ आप लाइन बफ़र विकल्प नहीं है grep के बजाय awk (एक और शानदार बैश उपयोगिता) का उपयोग करें! यह लगातार पूंछ से आपके डेटा को स्ट्रीम करेगा।

यह है कि आप grep का उपयोग कैसे करते हैं

tail -f <file> | grep pattern

इस तरह आप awk का उपयोग करेंगे

tail -f <file> | awk '/pattern/{print $0}'

6
यह सही नहीं है; बॉक्स से बाहर अर्क लाइन बफरिंग करता है, ज्यादातर अन्य मानक यूनिक्स टूल्स की तरह। (इसके अलावा, {print $0}निरर्थक है, क्योंकि जब स्थिति गुजरती है तो मुद्रण डिफ़ॉल्ट क्रिया है।)
ट्रिपल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.