लॉग फ़ाइल लाइनों के साथ टाइमस्टैम्प स्टैम्प लगाना


11

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

जवाबों:


18

सामान्य तरीका

$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log

यह काम किस प्रकार करता है:

  1. catनामक फ़ाइल को पढ़ता है input.logऔर इसे अपने मानक आउटपुट स्ट्रीम में प्रिंट करता है।

    आम तौर पर मानक आउटपुट एक टर्मिनल से जुड़ा होता है, लेकिन इस छोटी स्क्रिप्ट में |ऐसा शेल होता है catजो मानक इनपुट के मानक आउटपुट को पुनर्निर्देशित करता है sed

  2. sedडेटा पढ़ता है (जैसा कि catयह उत्पादन करता है), इसे संसाधित करता है ( -eविकल्प के साथ प्रदान की गई स्क्रिप्ट के अनुसार ) और फिर इसे अपने मानक आउटपुट पर प्रिंट करता है। स्क्रिप्ट का "s/^/$(date -R) /"अर्थ है date -Rकमांड द्वारा उत्पन्न पाठ के लिए लाइन की हर शुरुआत को बदलें (कमांड के लिए सामान्य निर्माण है:) s/pattern/replace/

  3. फिर एक फ़ाइल >> bashके आउटपुट को पुनर्निर्देशित किया sedजाता है जिसे कहा जाता है output.log( >मतलब फ़ाइल सामग्री को प्रतिस्थापित करता है और >>इसका अर्थ है अंत में जोड़ें)।

समस्या का $(date -R)मूल्यांकन एक बार जब आप स्क्रिप्ट चलाते हैं तो यह प्रत्येक लाइन की शुरुआत में वर्तमान टाइमस्टैम्प डालेगी। वर्तमान टाइमस्टैम्प एक संदेश उत्पन्न होने के क्षण से बहुत दूर हो सकता है। इससे बचने के लिए आपको संदेशों को संसाधित करना होगा क्योंकि वे फ़ाइल में लिखे गए हैं, क्रॉन जॉब के साथ नहीं।

फीफो

ऊपर वर्णित मानक धारा पुनर्निर्देशन को पाइप कहा जाता है । आप इसे न केवल |स्क्रिप्ट में आदेशों के बीच, बल्कि एक FIFO फ़ाइल (उर्फ नामित पाइप ) के माध्यम से पुनर्निर्देशित कर सकते हैं । एक प्रोग्राम फ़ाइल को लिखेगा और दूसरा डेटा पढ़ेगा और इसे पहले भेजे गए अनुसार प्राप्त करेगा।

एक उदाहरण चुनें:

$ mkfifo foo.log.fifo
$ while true; do cat foo.log.fifo | sed -e "s/^/$(date -R) /" >> foo.log; done;

# have to open a second terminal at this point
$ echo "foo" > foo.log.fifo
$ echo "bar" > foo.log.fifo
$ echo "baz" > foo.log.fifo

$ cat foo.log      

Tue, 20 Nov 2012 15:32:56 +0400 foo
Tue, 20 Nov 2012 15:33:27 +0400 bar
Tue, 20 Nov 2012 15:33:30 +0400 baz

यह काम किस प्रकार करता है:

  1. mkfifo एक नामित पाइप बनाता है

  2. while true; do sed ... ; doneएक अनंत लूप चलाता है और प्रत्येक पुनरावृत्ति पर यह अपने मानक इनपुट पर sedपुनर्निर्देशन के साथ चलता है foo.log.fifo; sed इनपुट डेटा की प्रतीक्षा में ब्लॉक और फिर प्राप्त संदेश को संसाधित करता है और इसे मानक आउटपुट पर प्रिंट करता है foo.log

    इस बिंदु पर आपको एक नया टर्मिनल विंडो खोलना होगा क्योंकि लूप वर्तमान टर्मिनल पर कब्जा कर लेता है।

  3. echo ... > foo.log.fifoअपने मानक आउटपुट के लिए एक संदेश प्रिंट करता है, जो पंद्रह फ़ाइल में रीडायरेक्ट sedहोता है और इसे प्राप्त करता है और इसे संसाधित करता है और एक नियमित फ़ाइल को लिखता है।

महत्वपूर्ण नोट फीफो है, जैसे कि किसी भी अन्य पाइप का कोई मतलब नहीं है अगर उसका एक पक्ष किसी भी प्रक्रिया से जुड़ा नहीं है। यदि आप एक पाइप को लिखने की कोशिश करते हैं तो वर्तमान प्रक्रिया तब तक अवरुद्ध हो जाएगी जब तक कोई पाइप के दूसरी तरफ डेटा नहीं पढ़ेगा। यदि आप पाइप से पढ़ना चाहते हैं तो प्रक्रिया तब तक अवरुद्ध रहेगी जब तक कोई व्यक्ति पाइप को डेटा नहीं लिखेगा। sedउदाहरण में पाश से ऊपर कुछ भी नहीं (सोता) करता है जब तक आप ऐसा echo

अपनी विशेष स्थिति के लिए आप केवल लॉग इन संदेशों को पंद्रह फ़ाइल में लिखने के लिए अपने एप्लिकेशन को कॉन्फ़िगर करते हैं। यदि आप इसे कॉन्फ़िगर नहीं कर सकते हैं - बस मूल लॉग फ़ाइल को हटा दें और एक फीनो फ़ाइल बनाएँ। लेकिन फिर से ध्यान दें कि अगर sedलूप किसी कारण से मर जाएगा - आपके प्रोग्राम को writeफ़ाइल में प्रयास करने पर अवरुद्ध कर दिया जाएगा जब तक कि कोई readपंद्रह से नहीं होगा ।

लाभ वर्तमान टाइमस्टैम्प का मूल्यांकन है और एक संदेश से जुड़ा हुआ है क्योंकि प्रोग्राम इसे फ़ाइल में लिखता है।

अतुल्यकालिक प्रसंस्करण के साथ tailf

लॉग को लिखने और अधिक स्वतंत्र प्रसंस्करण के लिए आप दो नियमित फ़ाइलों का उपयोग कर सकते हैं tailf। एक आवेदन एक कच्ची फ़ाइल को संदेश लिखेगा और दूसरी प्रक्रिया नई लाइनें पढ़ेगी (अतुल्यकालिक रूप से लिखने के लिए) और दूसरी फ़ाइल पर लिखने के साथ डेटा संसाधित करें।

आइए एक उदाहरण लेते हैं:

# will occupy current shell
$ tailf -n0 bar.raw.log | while read line; do echo "$(date -R) $line" >> bar.log; done;

$ echo "foo" >> bar.raw.log
$ echo "bar" >> bar.raw.log
$ echo "baz" >> bar.raw.log

$ cat bar.log

Wed, 21 Nov 2012 16:15:33 +0400 foo
Wed, 21 Nov 2012 16:15:36 +0400 bar
Wed, 21 Nov 2012 16:15:39 +0400 baz

यह काम किस प्रकार करता है:

  1. रन tailfप्रक्रिया जो लिखने का पालन करेगी bar.raw.logऔर उन्हें अनंत while read ... echoलूप पर पुनर्निर्देशित मानक आउटपुट पर प्रिंट करेगी । यह लूप दो क्रियाएं करता है: मानक इनपुट से डेटा को बफर वेरिएबल तक पढ़ा जाता है lineऔर फिर निम्न बफर डेटा के साथ उत्पन्न टाइमस्टैम्प को लिखें bar.log

  2. को कुछ संदेश लिखें bar.raw.log। आपको इसे एक अलग टर्मिनल विंडो में करना होगा क्योंकि पहले वाले का कब्जा tailfहोगा, जो राइट्स का पालन करेगा और अपना काम करेगा। काफी सरल।

यदि आप मारते हैं तो मुकदमा आपका आवेदन अवरुद्ध नहीं होगा tailf। विपक्ष कम सटीक टाइमस्टैम्प और लॉग फ़ाइलों को डुप्लिकेट कर रहा है।


धन्यवाद। .Fifo मेरे उपयोग के लिए बहुत उपयुक्त प्रतीत होता है। मेरा प्रोग्राम पहले से ही एक file.txt लॉग में लिखता है, लेकिन इस फ़ाइल को आपके foo.log.fifo. पर पुनर्निर्देशित किया जाना चाहिए। लेकिन $ tailf file.txt> foo.log.fifo हैंग करना ! तो मैं अपनी सामग्री को एक अद्यतन लॉग फ़ाइल में इस foo.log.fifo पर कैसे पुनर्निर्देशित कर सकता हूं ताकि यह समय भी जोड़ सके।
Kratos

बस जवाब सुधर गया। बताया कि क्यों tailf, आपके द्वारा इसे उपयोग करने का सही तरीका जोड़ा गया है। वास्तव में जिस तरह tailfसे यह अधिक सुरुचिपूर्ण लगता है, लेकिन मैंने उम्मीद के साथ पंद्रह रास्ता अपनाया, यह किसी के लिए उपयोगी होगा।
दिमित्री वासिलीनोव

Vmstat आउटपुट एनोटेट करने के लिए अपने sed उत्तर का उपयोग करने से टाइमस्टैम्प की पैदावार होती है जो नहीं बदलती है, vmstat 1 | sed -e "s / ^ / $ (तारीख -R) /"
ChuckCottrill


2

दिमित्री वासिलिनोव के जवाब से संशोधित।

बैश स्क्रिप्ट में, आप टाइमस्टैम्प लाइन के साथ आउटपुट को रीडायरेक्ट और रैप कर सकते हैं।

कब इस्तेमाल करें:

  • स्क्रिप्ट स्क्रिप्ट नौकरियों के लिए, मुख्य स्क्रिप्ट से पहले लाइन डालें
  • गैर-स्क्रिप्ट नौकरियों के लिए, प्रोग्राम को कॉल करने के लिए एक स्क्रिप्ट बनाएं।
  • सिस्टम द्वारा सेवाओं के नियंत्रण के tailfलिए, लॉग फ़ाइल के लिए उपयोग करना बेहतर है जैसा कि दिमित्री वासिलिनोव ने कहा।

एक उदाहरण का नाम foo.sh:

#!/bin/bash
exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;)

echo "foo"
sleep 1
echo "bar" >&2
sleep 1
echo "foobar"

और परिणाम:

$ bash foo.sh
$ cat foo.log
May 12 20:04:11 foo
May 12 20:04:12 bar
May 12 20:04:13 foobar

यह काम किस प्रकार करता है

  1. exec &> एक ही स्थान पर stdout और stderr पुनर्निर्देशित करें
  2. >( ... ) एक अतुल्यकालिक आंतरिक कमांड के लिए पाइप आउटपुट
  3. बाकी हिस्सा दिमित्री वासिलीनोव के रूप में काम करता है।

उदाहरण के लिए:

  • पाइप टाइमस्टैम्प और फ़ाइल में प्रवेश करें

    #!/bin/bash        
    exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;)
    
    echo "some script commands"
    /path-to/some-thrid-party-programs
    
  • या टाइमस्टैम्प प्रिंट करें और स्टडआउट में लॉग इन करें

    #!/bin/bash        
    exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line"; done;)
    
    echo "some script commands"
    /path-to/some-thrid-party-programs
    

    फिर उन्हें /etc/crontabसेटिंग में सहेजें

    * * * * * root /path-to-script/foo.sh >> /path-to-log-file/foo.log
    

1

मैंने tsइस तरह से एक स्क्रिप्ट के लिए एक त्रुटि लॉग में एक टाइम स्टैम्प के साथ एक प्रविष्टि प्राप्त करने के लिए उपयोग किया था जो मैं एक दूरस्थ होस्ट के आँकड़ों से भरा कैक्टि प्राप्त करने के लिए उपयोग करता हूं।

कैक्टि का परीक्षण करने के लिए मैं randकुछ यादृच्छिक मूल्यों को जोड़ने के लिए उपयोग करता हूं जो मैं अपने सिस्टम के तापमान की निगरानी के लिए तापमान ग्राफ के लिए उपयोग करता हूं।

Pushmonstats.sh एक स्क्रिप्ट है जो मेरे पीसी के सिस्टम तापमान के आंकड़े एकत्र करती है और इसे एक रास्पबेरी पाई को भेजती है जिस पर कैक्टस चलता है। कुछ समय पहले, नेटवर्क अटक गया था। मुझे केवल SSH का समय मेरी त्रुटि लॉग में मिला। दुर्भाग्य से, उस लॉग में कोई समय प्रविष्टियां नहीं हैं। मुझे नहीं पता था कि लॉग एंट्री में टाइम स्टैम्प कैसे जोड़ा जाता है। इसलिए, इंटरनेट पर कुछ खोजों के बाद, मैं इस पोस्ट पर ठोकर खाई और यही मैंने उपयोग किया ts

इसका परीक्षण करने के लिए, मैंने एक अज्ञात विकल्प का उपयोग किया rand। जिससे स्टादर को एक त्रुटि मिली। इसे पकड़ने के लिए, मैं इसे एक अस्थायी फ़ाइल पर पुनर्निर्देशित करता हूं। फिर मैं फ़ाइल की सामग्री को दिखाने के लिए बिल्ली का उपयोग करता हूं और इसे पाइप tsकरता हूं, एक समय प्रारूप जोड़ता हूं जो मुझे इस पोस्ट पर मिला और अंत में इसे त्रुटि फ़ाइल में लॉग इन करें। फिर मैं अस्थायी फ़ाइल की सामग्री को साफ करता हूं, अन्यथा मुझे उसी त्रुटि के लिए दोहरी प्रविष्टियां मिलती हैं।

crontab:

* * * * * /home/monusr/bin/pushmonstats.sh 1>> /home/monusr/pushmonstats.log 2> /home/monusr/.err;/bin/cat /home/monusr/.err|/usr/bin/ts %F-%H:%M:%.S 1>> /home/monusr/pushmonstats.err;> /home/monusr/.err

यह मेरी त्रुटि लॉग में निम्नलिखित देता है:

2014-03-22-19:17:53.823720 rand: unknown option -- '-l'

हो सकता है कि यह ऐसा करने का एक बहुत ही सुंदर तरीका नहीं है, लेकिन यह काम करता है। मुझे आश्चर्य है कि अगर वहाँ एक और अधिक सुंदर दृष्टिकोण है।

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