लॉग का पालन करने का सबसे अच्छा तरीका है और लॉग में कुछ पाठ दिखाई देने पर एक कमांड निष्पादित करें


54

मेरे पास एक सर्वर लॉग है जो टेक्स्ट की एक विशिष्ट लाइन को सर्वर के उठने पर उसकी लॉग फाइल में आउटपुट करता है। मैं सर्वर के उठने के बाद एक कमांड निष्पादित करना चाहता हूं, और इसलिए निम्न जैसा कुछ करना चाहिए:

tail -f /path/to/serverLog | grep "server is up" ...(now, e.g., wget on server)?

इसे करने का बेहतरीन तरीका क्या है?


3
tail -Fलॉग रोटेशन को संभालने के लिए उपयोग करना सुनिश्चित करें - यानी my.logपूर्ण हो जाता है और आगे बढ़ता है my.log.1और आपकी प्रक्रिया एक नया बनाता हैmy.log
एसजी

जवाबों:


34

एक सरल तरीका जागृत होगा।

tail -f /path/to/serverLog | awk '
                    /Printer is on fire!/ { system("shutdown -h now") }
                    /new USB high speed/  { system("echo \"New USB\" | mail admin") }'

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

open(my $fd, "<", "/path/to/serverLog") or die "Can't open log";
while(1) {
    if(eof $fd) {
        sleep 1;
        $fd->clearerr;
        next;
    }
    my $line = <$fd>;
    chomp($line);
    if($line =~ /Printer is on fire!/) {
        system("shutdown -h now");
    } elsif($line =~ /new USB high speed/) {
        system("echo \"New USB\" | mail admin");
    }
}

मुझे awkएक लाइन में फ्लाई पर छोटा और आसान करने के लिए समाधान पसंद है । हालाँकि, यदि मैं जिस कमांड को चलाना चाहता हूं, उसके उद्धरण हैं, तो यह थोड़ा बोझिल हो सकता है, क्या कोई विकल्प है, शायद पाइपलाइनों और यौगिक आदेशों का उपयोग करके जो एक संक्षिप्त एक-लाइनर समाधान की अनुमति देता है लेकिन परिणामी कमांड को पारित करने की आवश्यकता नहीं है। एक तार के रूप में?
जॉन्ड्री

1
@ आप स्क्रिप्ट के रूप में awk लिख सकते हैं। स्क्रिप्ट की पहली पंक्ति के रूप में "#! / Usr / bin awk -f" का उपयोग करें। यह मेरे उदाहरण में बाहरी एकल उद्धरणों की आवश्यकता को समाप्त करेगा और उन्हें system()कमांड के अंदर उपयोग के लिए मुक्त करेगा ।
पेंग्विन 359

@ penguin359, सच है, लेकिन यह अभी भी कमांड लाइन से ऐसा करना दिलचस्प होगा। मेरे मामले में, कई अलग-अलग चीजें हैं, जिन्हें मैं बहुत सी चीजों को शामिल करना चाहता हूं, जिन्हें मैं पूर्वाभास नहीं कर सकता हूं, इसलिए यह सिर्फ सर्वर को शुरू करने और एक लाइन में यह सब करने में सक्षम होना सुविधाजनक है।
जॉन्ड्री

मुझे एक विकल्प मिला, हालाँकि मुझे नहीं पता कि यह कितना ठोस है:tail -f /path/to/serverLog | grep "server is up" | head -1 && do_some_command
२०:२०

@ जो इस तरह से सिर का उपयोग करके थोड़ा नाजुक लगता है। इससे भी महत्वपूर्ण बात, यह मेरे उदाहरणों की तरह दोहराए जाने योग्य नहीं है। यदि "सर्वर ऊपर है" लॉग की अंतिम दस लाइनों में है, तो यह कमांड को आग देगा और तुरंत बाहर निकल जाएगा। यदि आप इसे पुनः आरंभ करते हैं, तो यह सबसे अधिक संभावना है कि आग और फिर से बाहर निकलेगा जब तक कि "सर्वर" नहीं है दस पंक्तियों को लॉग में जोड़ा गया है। उस का एक संशोधन जो बेहतर काम कर सकता है, tail -n 0 -f /path/to/serverLog वह यह है कि फ़ाइल की अंतिम 0 लाइनें पढ़ें, फिर प्रिंट करने के लिए और लाइनों की प्रतीक्षा करें।
पेंग्विन 359

16

आप केवल एक संभावना की तलाश में और के बजाय का उपयोग कर खोल में ज्यादातर रहना चाहते हैं कर रहे हैं awkया perl, आप की तरह कुछ कर सकता है:

tail -F /path/to/serverLog | 
grep --line-buffered 'server is up' | 
while read ; do my_command ; done

... जो लॉग फ़ाइल में my_command" सर्वर अप है " हर बार दिखाई देगा। कई संभावनाओं के लिए, आप शायद छोड़ सकते हैं grepऔर इसके बजाय caseभीतर का उपयोग कर सकते हैं while

राजधानी घुमाए जाने के लिए लॉग फ़ाइल देखने के लिए -Fकहती tailहै; यानी अगर वर्तमान फ़ाइल का नाम बदला जाता है और एक ही नाम के साथ एक और फ़ाइल अपनी जगह लेता है, tailनई फ़ाइल में परिवर्तित कर देगा।

--line-bufferedविकल्प बताता है grepहर पंक्ति के बाद अपने बफर फ्लश करने के लिए; अन्यथा, my_commandसमय पर फैशन तक नहीं पहुंचा जा सकता है (यह मानते हुए कि लॉग में काफी आकार की रेखाएं हैं)।


2
मुझे वास्तव में यह उत्तर पसंद है, लेकिन यह मेरे लिए पहले काम नहीं करता था। मुझे लगता है कि आपको --line-bufferedविकल्प जोड़ने की आवश्यकता है grep, या अन्यथा यह सुनिश्चित करें कि यह लाइनों के बीच अपने आउटपुट को फ्लश करता है: अन्यथा, यह बस लटका रहता है, और my_commandकभी भी नहीं पहुंचता है। यदि आप पसंद करते हैं ack, तो इसका एक --flushझंडा है; यदि आप पसंद करते हैं ag, तो साथ लपेटकर देखें stdbufstackoverflow.com/questions/28982518/…
doctaphred

मैंने यह प्रयोग करके देखा do exit ;। यह ठीक काम करने के लिए लग रहा था, लेकिन पूंछ कभी खत्म नहीं हुई और हमारी स्क्रिप्ट अगली पंक्ति में कभी नहीं चली गई। क्या doअनुभाग में पूंछ को रोकने का एक तरीका है ?
माचिस

14

यह प्रश्न पहले से ही उत्तर दिया जा रहा है, लेकिन मुझे लगता है कि एक बेहतर समाधान है।

इसके बजाय tail | whatever, मुझे लगता है कि आप वास्तव में क्या चाहते हैं swatch। स्वैच एक प्रोग्राम है जिसे स्पष्ट रूप से उस कार्य के लिए तैयार किया गया है जो आप पूछ रहे हैं, एक लॉग फाइल को देखना और लॉग लाइनों के आधार पर क्रियाओं को निष्पादित करना। उपयोग करने के tail|fooलिए आवश्यक है कि आपको ऐसा करने के लिए सक्रिय रूप से एक टर्मिनल मिला हो। दूसरी ओर स्वैच एक डेमॉन के रूप में चलता है और हमेशा आपके लॉग देखता रहेगा। सभी लिनक्स डिस्ट्रो में स्वैच उपलब्ध है,

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

स्वैच पर सबसे अच्छा 30 सेकंड का ट्यूटोरियल मैं यहां पा सकता हूं: http://www.campin.net/newlogcheck.html


1
यही कारण है कि ट्यूटोरियल अब 404 है: /
therefromhere

1
WebArchive आपका मित्र है: web.archive.org/web/20140922041805/http://campin.net/…
Sun

10

यह अजीब है कि किसी ने multitailउपयोगिता के बारे में उल्लेख नहीं किया है जिसमें यह कार्यक्षमता आउट-ऑफ-बॉक्स है। उपयोग उदाहरण में से एक:

पिंग-कमांड का आउटपुट दिखाएं और यदि यह टाइमआउट प्रदर्शित करता है, तो वर्तमान में लॉग इन किए गए सभी उपयोगकर्ताओं को एक संदेश भेजें

multitail -ex timeout "echo timeout | wall" -l "ping 192.168.0.1"

उपयोग का एक और उदाहरण भी देखें multitail


+1, मुझे नहीं पता था कि `मल्टीटैल में उन प्रकार के निंजा कौशल थे, जिन्हें दूर रखा गया था। यह बात बताने के लिए धन्यवाद।
कालेब

8

खुद से काम कर सकता है

आइए देखें कि यह कितना सरल और पठनीय हो सकता है:

mylog() {
    echo >>/path/to/myscriptLog "$@"
}

while read line;do
    case "$line" in
        *"Printer on fire"* )
            mylog Halting immediately
            shutdown -h now
            ;;
        *DHCPREQUEST* )
            [[ "$line" =~ DHCPREQUEST\ for\ ([^\ ]*)\  ]]
            mylog Incomming or refresh for ${BASH_REMATCH[1]}
            $HOME/SomethingWithNewClient ${BASH_REMATCH[1]}
            ;;
        * )
            mylog "untrapped entry: $line"
            ;;
    esac
  done < <(tail -f /path/to/logfile)

जबकि आप बैश का उपयोग नहीं करते हैं regex, यह बहुत जल्दी रह सकता है!

लेकिन + एक बहुत ही कुशल और दिलचस्प अग्रानुक्रम है

लेकिन उच्च लोड सर्वर के लिए, और जैसा कि मुझे पसंद है sedक्योंकि यह बहुत जल्दी और बहुत स्केलेबल है, मैं अक्सर इसका उपयोग करता हूं:

while read event target lost ; do
    case $event in
        NEW )
            ip2int $target intTarget
            ((count[intTarget]++))
        ...

    esac
done < <(tail -f /path/logfile | sed -une '
  s/^.*New incom.*from ip \([0-9.]\+\) .*$/NEW \1/p;
  s/^.*Auth.*ip \([0-9.]\+\) failed./FAIL \1/p;
  ...
')

6

यही कारण है कि मैं यह भी करना शुरू कर दिया है, लेकिन इसके साथ बहुत अधिक परिष्कृत हो गया है। कुछ बातों का ध्यान रखना चाहिए:

  1. यदि लॉग की पूंछ में पहले से ही "सर्वर ऊपर है"।
  2. एक बार मिल जाने पर पूंछ की प्रक्रिया को स्वचालित रूप से समाप्त करना।

मैं इस की तर्ज पर कुछ का उपयोग करता हूं:

RELEASE=/tmp/${RANDOM}$$
(
  trap 'false' 1
  trap "rm -f ${RELEASE}" 0
  while ! [ -s ${RELEASE} ]; do sleep 3; done
  # You can put code here if you want to do something
  # once the grep succeeds.
) & wait_pid=$!
tail --pid=${wait_pid} -F /path/to/serverLog \
| sed "1,10d" \
| grep "server is up" > ${RELEASE}

यह tailतब तक खुला रखने से काम करता है जब तक कि ${RELEASE}फाइल में डेटा न हो।

एक बार grepसफल होने के बाद :

  1. उत्पादन करने के लिए लिखता है ${RELEASE}जो होगा
  2. ${wait_pid}करने के लिए प्रक्रिया को समाप्त
  3. बाहर निकलें tail

नोट: sedवास्तव tailमें स्टार्टअप पर उत्पादन लाइनों की संख्या और उस नंबर को हटाने के लिए निर्धारित करने के लिए अधिक परिष्कृत हो सकता है । लेकिन आम तौर पर, यह 10 है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.