`पूंछ -f` जब तक पाठ नहीं देखा जाता है


20

मुझे एक कमांड-लाइन इंटरफ़ेस वाला CI सर्वर मिला है, जो मुझे एक जॉब ( jenkinsCI सर्वर और jenkins-cli.jarटूल) को दूरस्थ रूप से किक-ऑफ करने की अनुमति देता है ।

जब मैं नौकरी छोड़ देता हूं tail -fतब मैं लॉग इन करता हूं (गन्दा आदेश के लिए क्षमा करें):

ssh -t my-jenkins-host.com "tail -f \"/var/lib/jenkins/jobs/$job_name/builds/\`ls -ltr /var/lib/jenkins/jobs/$job_name/builds/ | grep '^l' | tail -n 1|awk '{print \$9}'\`/log\""

नौकरी सफलतापूर्वक पूरी होने के बाद, आमतौर पर कम से कम 5 मिनट के बाद, मुझे आउटपुट पर निम्न पंक्ति मिलती है:

Finished: SUCCESS

क्या इस बिंदु पर लॉग को रोकने के लिए एक अच्छा तरीका है? यानी एक tail_until 'some line' my-file.logआदेश की तरह है ?

बोनस: अतिरिक्त क्रेडिट यदि आप एक उत्तर दे सकते हैं जो 0 तब रिटर्न करता है जब SUCCESS का मिलान होता है, 1 जब FAILURE मिलान होता है, और आपका समाधान मैक पर काम करता है! (जो मुझे लगता है कि bsd आधारित है)

जवाबों:


39

आप पाइप कर सकते हैं tail -fमें sed, जब यह लाइन आपके लिए हैं खोज देखता छोड़ने की यह कह रही:

tail -f /path/to/file.log | sed '/^Finished: SUCCESS$/ q'

sedप्रत्येक पंक्ति को डिफ़ॉल्ट रूप से संसाधित करता है, और उस रेखा को देखने के बाद बाहर निकलें। tailप्रक्रिया जब यह अगली पंक्ति लिखने के लिए कोशिश करता है और देखता है इसके उत्पादन पाइप टूट गया है बंद हो जाएगा


बोह य! उत्तम। ... तो किसी भी मौके से 0 से बाहर निकलने का एक तरीका है अगर मैं एक चीज़ ('SUCCESS') से मेल खाता हूं और 1 अगर मैं कुछ और मिलान करता हूं (जैसे कि शायद 'असफल')?
एरोनस्टेसी

7
@ARonstacy यदि आप GNU grep का उपयोग कर रहे हैं, तो qकमांड एक वैकल्पिक निकास कोड लेता है। तो sedउसकी कमांड यह होगीsed '/^Finished: SUCCESS$/ q0; /^Finished: FAILURE$/ q1'
माइकल Mrozek

6
यदि Finished: SUCCESSआउटपुट की अंतिम पंक्ति
lk-


1
इस समाधान का एक प्रमुख दोष है: मेरे मामले में खोज पंक्ति द्वारा लॉग समाप्त होता है। कोई और रेखा नहीं लिखी जाएगी, इसलिए यह प्रक्रिया
रुकी रहेगी

6
tail -f my-file.log | grep -qx "Finished: SUCCESS"

-q, जिसका अर्थ है शांत, जैसे ही यह एक मैच पाता है

-xgrepपूरी लाइन से मेल खाता है

दूसरे भाग के लिए, प्रयास करें

tail -f my-file.log | grep -m 1 "^Finished: " | grep -q "SUCCESS$"

-m <number>नंबर मैच के बाद बंद करने के लिए grep बताता है

और grep -qबाहर निकलने की स्थिति केवल तभी होगी 0जब SUCCESSलाइन के अंत में पाया जाएगा

यदि आप सभी आउटपुट देखना चाहते हैं, तो आप उपयोग नहीं कर सकते grep -q, लेकिन आप अभी भी कर सकते हैं

tail -f my-file.log | grep -m 1 "^Finished: "

यदि सब कुछ FAILUREदिखाई देने पर बाहर निकलने की स्थिति को 1 पर सेट करता है।


5
मैंने grepमूल रूप से अपने उत्तर में उपयोग किया , लेकिन अगर वह उपयोग कर रहा है tail -fतो वह शायद फ़ाइल आउटपुट देखना चाहता है; grepनहीं सभी मध्यवर्ती लाइनों को दिखाने के लिए जा रहा है
माइकल Mrozek

4

@ मर्ज़ेक की टिप्पणियों के साथ @ मिकेल के उत्तर पर एक भिन्नता (मैंने टिप्पणी पर जवाब दिया होता लेकिन मुझे लगता है कि मेरे पास अभी तक कोई विशेषाधिकार नहीं हैं)

tail -f my-file.log | tee >( grep -qx "Finished: SUCCESS" )

आपको @ मिकेल के समाधान का उपयोग करने की अनुमति देगा और फिर भी स्क्रीन पर आउटपुट देख सकता है


क्या हम इसमें एक टाइमआउट इंटरवैल जोड़ सकते हैं, जैसे: "अगर इसकी 60 से 120 सेकंड के बीच नहीं पढ़ा जाता है, तो पूंछ को निरस्त करें और शेल में एक त्रुटि निकास कोड दें"?
किलटेक

2

मुझे यहाँ कोई जवाब पसंद नहीं आया, इसलिए मैंने अपना रोल करने का फैसला किया। यह बैश स्क्रिप्ट सभी मानदंडों को पूरा करती है, और विफलता पर 1 से बाहर निकलने के लिए BONUS भी शामिल है।

#!/bin/bash
while IFS= read -r LOGLINE || [[ -n "$LOGLINE" ]]; do
    printf '%s\n' "$LOGLINE"
    [[ "${LOGLINE}" == "Finished: SUCCESS" ]] && exit 0
    [[ "${LOGLINE}" == "Finished: FAILURE" ]] && exit 1
done < <(timeout 300 tail -f my-file.log)
exit 3

इसमें टाइमआउट फीचर भी शामिल है, जिसके परिणामस्वरूप 3. का एक एग्जिट कोड होगा। यदि आपके पास अपने सिस्टम पर टाइमआउट कमांड नहीं है, तो एंथोनी थिसेन से टाइमआउट.श स्क्रिप्ट को पकड़ो:

http://www.ict.griffith.edu.au/anthony/software/timeout.sh

नीचे दी गई टिप्पणियों के अनुसार, मैंने भागने के चरित्र विस्तार को रोकने के लिए लॉग प्रिंट को अपडेट किया और एक मानक 'रीड' की सभी विशेषताओं को शामिल किया। पूर्ण 'पठन' विवरण के लिए /programming//a/10929511 देखें । EOF चेक यहां आवश्यक नहीं है, लेकिन पूर्णता के लिए शामिल है।


बहुत अच्छा। while IFS= read -r LOGLINEसे लाइनों पर बंटवारे वाले व्हॉट्सएप के प्रदर्शन को रोकने के लिए उपयोग करने पर विचार करें tail
रोजी

@roaima: readविभाजित नहीं होता है जब केवल एक चर होता है (और इसके साथ एक सरणी नहीं है -a), लेकिन आपको -rइनपुट डेटा बैकस्लैश में होने की आवश्यकता नहीं है। लेकिन यदि इनपुट डेटा में बैकस्लैश है, तो echo "$var"आपके शेल और / या सिस्टम के आधार पर भी printf '%s\n' "$line"
खराब हो सकता है


0

यहाँ एक अजगर लिपि है जो लगभग वही करती है जो मैं चाहता हूँ (नीचे केवेट देखें):

import sys,re

def main():
    re_end = re.compile(sys.argv[1])
    re_fail = re.compile(sys.argv[2]) if len(sys.argv) > 2 else None
    for line in sys.stdin:
        sys.stdout.write(line)
        if re_end.match(line):
            sys.exit(0)
        elif re_fail and re_fail.match(line):
            sys.exit(1)

if __name__ == '__main__': main()

चेतावनियां:

  • लाइनों के रूप में वे आते हैं में मुद्रित नहीं कर रहे हैं ... वे समूहों में मुद्रित कर रहे हैं ... लगता है कुछ बफ़रिंग चल रहा है

  • मुझे इसे अपने पथ या किसी चीज़ पर स्क्रिप्ट के रूप में स्थापित करना होगा, इसलिए यह असुविधाजनक है, और मैं एक स्लीक वन-लाइन पसंद करूंगा :)


अद्यतन: tailएक ही बफरिंग करने लगता है, इसलिए मुझे लगता है कि यह ऐसा कुछ नहीं है जो चारों ओर काम करने की कोशिश कर रहा हो।
एरोनॉस्टेसी

0

मैं के साथ समस्या नहीं थी sedऔर grepऔर उनके विकल्पों, तो मैं मेरा लिखनाone with bash conditions

tail -f screenlog.* | 
while IFS= read line; 
 do 
   echo $line; 
   if [[ $line == *Started\ Application* ]]; 
    then pkill tail; 
   fi; 
done

-1

आप भी आजमाएं

 grep -q 'App Started' <(tail -f /var/log/app/app.log)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.