2011-08-24 16 views
7

मैं एक ऐसी स्क्रिप्ट को लागू करने की कोशिश कर रहा हूं जो लॉग फ़ाइल में एक विशिष्ट संदेश की प्रतीक्षा करे। एक बार संदेश लॉग हो जाने के बाद मैं स्क्रिप्ट जारी रखना चाहता हूं।'grep -q' 'tail -f' से बाहर नहीं निकलता

यहाँ है कि मैं क्या tail -f और grep -q के साथ बाहर कोशिश कर रहा हूँ है:

# tail -f logfile | grep -q 'Message to continue' 

grep हार नहीं मानते और इसलिए यह हमेशा के लिए इंतजार कर रहा है, भले ही 'जारी रखने के लिए संदेश' फ़ाइल में लॉग होता है।

जब मैं -f के बिना इसे चलाता हूं तो यह ठीक काम करता प्रतीत होता है।

+0

यह पूंछ में क्या हो रहा बफरिंग से संबंधित हो सकता है। जब मैं आपका आदेश चलाता हूं तो यह बाहर नहीं निकलता है, लेकिन फ़ाइल को एक और लिखने के बाद बाहर निकलता है। – Kevin

उत्तर

9

tail -f बाद में एक फ़ाइल और डिस्प्ले लाइनों को पढ़ेगा, इसे समाप्त नहीं किया जाएगा (जब तक SIGTERM जैसे सिग्नल भेजे जाते हैं)। grep यहां अवरुद्ध हिस्सा नहीं है, tail -f है। grep पाइप से तब तक पढ़ेगा जब तक कि यह बंद न हो जाए, लेकिन ऐसा कभी नहीं होता क्योंकि tail -f बाहर नहीं निकलता है और पाइप खुलता रहता है।


आपकी समस्या का समाधान शायद (परीक्षण नहीं किया और बहुत बुरी तरह से प्रदर्शन करने की संभावना) किया जाएगा:

tail -f logfile | while read line; do 
    echo $line | grep -q 'find me to quit' && break; 
done 
+0

विस्तार के बिंदु के रूप में, बाधा, छोड़ें, और अन्य सिग्नल भी 'tail -f' को रोकते हैं। फिर भी, आपका निदान मूल रूप से सही है। –

+0

@ जोनाथन: लेकिन मैं grep के manpage पढ़ने के बाद उलझन में हूँ। '-q' के साथ पहले मैच के तुरंत बाद बाहर निकलना है, इसलिए ओप ** का उदाहरण ** काम करना चाहिए। grep quits और पाइप – knittl

+0

से पढ़ने बंद करो हाँ, मैं भी ... मैं इसके बारे में परेशान हूँ। यह मेरे लिए एक 'नया' व्यवहार है; मुझे '-q' के बराबर' -q' याद है, और प्रारंभिक समाप्ति आश्चर्यजनक है। मेरा सबसे अच्छा अनुमान यह है कि 'grep' पढ़ने के लिए जारी रखने के द्वारा' पूंछ 'को एक सिगिप भेजना टाल रहा है, लेकिन मैंने इसे साबित नहीं किया है। (मैं दूसरी वाक्य को हटाने के लिए अपनी टिप्पणी संपादित करने जा रहा था, लेकिन मुझे समय पर नहीं मिला।) –

0

क्योंकि tail-f (अनुसरण करें) विकल्प के साथ छोड़ नहीं करता है, और यही कारण है कि जारी है grep पर आउटपुट प्रदान करने के लिए। एक लॉग फ़ाइल में लाइनों की प्रतीक्षा करना शायद पर्ल/पायथन के साथ आसान होगा।

पायथन उपप्रोसेसर मॉड्यूल के साथ tail -f लॉन्च करें। एक लूप में tail से आउटपुट पढ़ें जब तक कि आप अपनी इच्छित रेखाएं नहीं देखते हैं, फिर पाइथन स्क्रिप्ट से बाहर निकलें। इस समाधान को अपनी खोल स्क्रिप्ट के अंदर रखें।

पायथन स्क्रिप्ट शैल स्क्रिप्ट को अवरुद्ध कर देगा जब तक वांछित रेखाएं नहीं देखी जातीं।

0

मैंने सोचा कि मैं एक जवाब के रूप में पोस्ट करता हूँ, क्योंकि यह बताता है कि क्यों आदेश बाहर निकलता फाइल करने के लिए एक दूसरे लिखने के बाद:

touch xxx 
tail -f xxx | grep -q 'Stop' 
ps -ef |grep 'grep -q' 
# the grep process is there 
echo "Stop" >> xxx 
ps -ef|grep 'grep -q' 
# the grep process actually DID exit 
printf "\n" >> xxx 
# the tail process exits, probably because it receives a signal when it 
# tries to write to a closed pipe 
+1

दरअसल, 'tail -f' को' SIGPIPE 'भेजा जाता है जब यह पाइप पर नया आउटपुट लिखने की कोशिश करता है _after_ पाइप पर पाठक बाहर निकल गया है। 'Tail -f' के साथ समस्या यह है कि फ़ाइल की "पूंछ" _usually_ एक पाइप पर एक ही लिखने में फिट होगी और भले ही पाठक केवल पहले बाइट को पढ़ता है और बाहर निकलता है,' सिगिपिप 'को तब तक नहीं भेजा जाएगा जब तक बाद के लेखन का प्रयास किया जाता है। –

3

कुछ प्रयोग करने के बाद, मेरा मानना ​​है कि समस्या यह है कि जिस तरह से bash में है किसी भी आकार या रूप में, छोड़ने के लिए एक पाइपलाइन में सभी प्रक्रियाओं की प्रतीक्षा करता है।

सी स्रोत (कार्यक्रम श्रेणीबद्ध में कई बार की एक किस्म), में से कुछ 360 लाइनों की एक सादे फ़ाइल 'QQQ' के साथ

और 'ग्रेप -q वापसी', का उपयोग कर तो मैं पर ध्यान दें:

  1. tail -n 300 qqq | grep -q return करता है लगभग एक बार बाहर निकलें।
  2. tail -n 300 -f qqq | grep -q return बाहर नहीं निकलता है।
  3. tail -n 300 -f qqq | strace -o grep.strace -q return बाधित होने तक बाहर नहीं निकलता है। grep.strace फ़ाइल के साथ समाप्त होता है:

    read(0, "#else\n#define _XOPEN_SOURCE 500\n"..., 32768) = 10152 
    close(1)        = 0 
    exit_group(0)       = ? 
    

    यह भी मुझे सुराग को लगता है कि grep से बाहर निकल गया है इससे पहले कि बाधा tail को मारता है, अगर यह किसी चीज़ की प्रतीक्षा कर रहा था, तो संकेत मिलेगा कि इसे संकेत मिलेगा।

  4. एक साधारण प्रोग्राम जो खोलता है, सिमुलेशन करता है, लेकिन प्रतीक्षा के बिना, इंगित करता है कि चीजें समाप्त हो जाती हैं।

    #define _XOPEN_SOURCE 600 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <stdarg.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <stdio.h> 
    
    static void err_error(const char *fmt, ...) 
    { 
        int errnum = errno; 
        va_list args; 
        va_start(args, fmt); 
        vfprintf(stderr, fmt, args); 
        va_end(args); 
        if (errnum != 0) 
         fprintf(stderr, "%d: %s\n", errnum, strerror(errnum)); 
        exit(1); 
    } 
    
    int main(void) 
    { 
        int p[2]; 
        if (pipe(p) != 0) 
         err_error("Failed to create pipe\n"); 
        pid_t pid; 
        if ((pid = fork()) < 0) 
         err_error("Failed to fork\n"); 
        else if (pid == 0) 
        { 
         char *tail[] = { "tail", "-f", "-n", "300", "qqq", 0 }; 
         dup2(p[1], 1); 
         close(p[0]); 
         close(p[1]); 
         execvp(tail[0], tail); 
         err_error("Failed to exec tail command"); 
        } 
        else 
        { 
         char *grep[] = { "grep", "-q", "return", 0 }; 
         dup2(p[0], 0); 
         close(p[0]); 
         close(p[1]); 
         execvp(grep[0], grep); 
         err_error("Failed to exec grep command"); 
        } 
        err_error("This can't happen!\n"); 
        return -1; 
    } 
    
    एक निश्चित आकार फ़ाइल के साथ

    , tail -f बाहर निकलने के लिए नहीं जा रहा है - तो खोल (bash) के चारों ओर लटका रहा है।

  5. tail -n 300 -f qqq | grep -q return चारों ओर लटका, लेकिन जब मैंने qqq फ़ाइल में एक और 300 लाइन जोड़ने के लिए एक और टर्मिनल का उपयोग किया, तो आदेश निकला। मैं इसे होने के रूप में समझता हूं क्योंकि grep निकल गया था, इसलिए जब tail ने पाइप को नया डेटा लिखा, तो उसे एक सिगिप और निकाला गया, और bash इसलिए मान्यता मिली कि पाइपलाइन की सभी प्रक्रियाएं मर गईं।

मैंने ksh और bash दोनों के साथ समान व्यवहार देखा। यह सुझाव देता है कि यह एक बग नहीं है लेकिन कुछ अपेक्षित व्यवहार है। एक x86_64 मशीन पर लिनक्स (आरएचईएल 5) पर परीक्षण।

+4

अच्छा विश्लेषण! दिलचस्प बात है, 'grep -q पैटर्न <(tail -f logfile)' ठीक काम करता है। –

+0

@ करोलो हॉर्वथ यह अभी तक कोई जवाब क्यों नहीं है? –

3
tail -f logfile | grep --max-count=1 -q 'Message to continue' 

बेशक, यह साइट छोड़कर चला जाता अगली पंक्ति का मिलान नहीं हुआ एक पर, पढ़ा जाता है तुरंत नहीं।

0

मैं अपनी परियोजना के लिए इसका उत्तर खोज रहा था। एक वीएमवेयर ESXi वीएम पर वास्तव में जीपीयू के माध्यम से पारित होने पर परीक्षण करने की कोशिश कर रहा है। एक ही प्रश्न के कई बदलाव हर जगह हैं। यह एक बहुत हालिया है। मैंने इसे मूर्ख बनाने का एक तरीका निकाला, और यदि आप लॉग में दोहराई गई अपनी रोचक रेखा के साथ रह सकते हैं तो:

tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >>/var/log/ vmkernel.log

यह लॉग में पूंछ करता है, एक समय में एक पंक्ति, grep पहली घटना के लिए प्रत्येक पंक्ति को जांचता है, और इसे लॉग में जोड़ता है तो पूंछ तुरंत छोड़ देता है।

VMware जैसी आप तो हैकिंग passthough, यहाँ और अधिक पढ़: http://hackaday.io/project/1071-the-hydra-multiheaded-virtual-computer

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