การต่อท้ายประทับเวลาพร้อมกับบรรทัดไฟล์บันทึก


11

ฉันมีล็อกไฟล์และฉันต้องการเพิ่มการประทับเวลาในแต่ละบรรทัดเมื่อเพิ่ม ดังนั้นฉันกำลังมองหาสคริปต์ที่เพิ่มการประทับเวลาในแต่ละรายการในบรรทัดบันทึกและที่สามารถทำงานเป็นงาน cron

คำตอบ:


18

วิธีการทั่วไป

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

มันทำงานอย่างไร:

  1. catอ่านไฟล์ที่เรียกinput.logและพิมพ์ไปยังสตรีมเอาต์พุตมาตรฐาน

    ปกติออกมาตรฐานมีการเชื่อมต่อไปยังสถานี แต่สคริปต์เล็ก ๆ น้อย ๆ นี้มี|การเปลี่ยนเส้นทางเพื่อให้เปลือกออกมาตรฐานของการป้อนข้อมูลมาตรฐานcatsed

  2. sedอ่านข้อมูล ( catสร้างข้อมูล) ประมวลผล (ตามสคริปต์ที่ให้มาพร้อมกับ-eตัวเลือก) แล้วพิมพ์ไปยังเอาต์พุตมาตรฐาน สคริปต์"s/^/$(date -R) /"วิธีการเปลี่ยนจุดเริ่มต้นของทุกบรรทัดกับข้อความที่สร้างโดยdate -Rคำสั่ง (การก่อสร้างทั่วไปสำหรับการเปลี่ยนคำสั่ง: s/pattern/replace/)

  3. จากนั้นตามการ>> bashเปลี่ยนเส้นทางเอาต์พุตของsedไปยังไฟล์ที่เรียกว่าoutput.log( >หมายถึงแทนที่เนื้อหาไฟล์และ>>หมายถึงการผนวกท้าย)

ปัญหาคือการ$(date -R)ประเมินครั้งเดียวเมื่อคุณเรียกใช้สคริปต์ดังนั้นมันจะแทรกการประทับเวลาปัจจุบันไปยังจุดเริ่มต้นของแต่ละบรรทัด การประทับเวลาปัจจุบันอาจห่างจากช่วงเวลาหนึ่งเมื่อมีการสร้างข้อความ เพื่อหลีกเลี่ยงมันคุณต้องประมวลผลข้อความตามที่เขียนไปยังไฟล์ไม่ใช่งาน cron

FIFO

เปลี่ยนเส้นทางกระแสมาตรฐานอธิบายไว้ข้างต้นเรียกว่าท่อ คุณสามารถเปลี่ยนเส้นทางไม่ใช่เพียงแค่|ระหว่างคำสั่งในสคริปต์ แต่ผ่านไฟล์ 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พิมพ์ข้อความไปยังเอาต์พุตมาตรฐานเปลี่ยนเส้นทางไปยังไฟล์ fifo และsedรับและประมวลผลและเขียนไปยังไฟล์ปกติ

หมายเหตุสำคัญคือฟีฟ่าเช่นเดียวกับท่ออื่น ๆ ที่ไม่มีความรู้สึกหากด้านใดด้านหนึ่งไม่ได้เชื่อมต่อกับกระบวนการ หากคุณพยายามเขียนไปที่ไพพ์กระบวนการปัจจุบันจะบล็อกจนกว่าจะมีคนอ่านข้อมูลทางด้านอื่นของไพพ์ หากคุณต้องการอ่านจากไปป์กระบวนการจะบล็อกจนกว่าจะมีคนเขียนข้อมูลไปยังไปป์ sedห่วงในตัวอย่างข้างต้นไม่ทำอะไรเลย (นอน) echoจนกว่าคุณจะทำ

สำหรับสถานการณ์เฉพาะของคุณคุณเพียงกำหนดค่าแอปพลิเคชันของคุณให้เขียนข้อความบันทึกลงในไฟล์ Fifo หากคุณไม่สามารถกำหนดค่าได้เพียงลบไฟล์บันทึกดั้งเดิมแล้วสร้างไฟล์ Fifo แต่โปรดทราบอีกครั้งว่าถ้าsedลูปจะตายด้วยเหตุผลบางอย่าง - โปรแกรมของคุณจะถูกบล็อกเมื่อพยายามไปwriteยังไฟล์จนกว่าจะมีคนreadมาจากฟีฟ่า

ประโยชน์คือการประทับเวลาปัจจุบันที่ประเมินและแนบกับข้อความขณะที่โปรแกรมเขียนลงไฟล์

การประมวลผลแบบอะซิงโครนัสด้วย tailf

tailfที่จะทำให้การเขียนเพื่อบันทึกและประมวลผลเป็นอิสระมากขึ้นคุณสามารถใช้สองไฟล์ปกติด้วย แอปพลิเคชันจะเขียนข้อความไปยังไฟล์ raw และกระบวนการอื่นอ่านบรรทัดใหม่ (ตามเพื่อเขียนแบบอะซิงโครนัส) และประมวลผลข้อมูลด้วยการเขียนไปยังไฟล์ที่สอง

ลองมาตัวอย่าง:

# 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ลูปไม่สิ้นสุด วงนี้จะดำเนินการสองการกระทำ: อ่านข้อมูลจากอินพุตมาตรฐานให้กับตัวแปรบัฟเฟอร์ที่เรียกว่าและเวลาแล้วที่สร้างเขียนด้วยข้อมูลที่บัฟเฟอร์ต่อไปนี้linebar.log

  2. bar.raw.logเขียนข้อความบางอย่างเพื่อ คุณต้องทำสิ่งนี้ในหน้าต่างเทอร์มินัลแยกต่างหากเพราะอันแรกจะถูกครอบครองโดยtailfที่จะติดตามการเขียนและทำงานของมัน ค่อนข้างง่าย

tailfข้อดีคือใบสมัครของคุณจะไม่ปิดกั้นถ้าคุณฆ่า ข้อเสียคือการประทับเวลาที่แม่นยำน้อยลงและการทำซ้ำไฟล์บันทึก


ขอบคุณ. Fifo ดูเหมือนจะฉลาดมากสำหรับการใช้โปรแกรม. my ของฉันแล้วเขียนในบันทึก file.txt แต่ไฟล์นี้จะต้องถูกเปลี่ยนเส้นทางไปยัง foo.log.fifo.But ของคุณ แต่ทำ $ tailf file.txt> foo.log.fifo hangs ! ดังนั้นฉันจะเปลี่ยนเส้นทางเนื้อหาของฉันในไฟล์บันทึกการอัปเดตไปยัง foo.log.fifo นี้ได้อย่างไรเพื่อให้สามารถผนวกเวลาได้อีกด้วย
Kratos

เพิ่งปรับปรุงคำตอบ อธิบายว่าทำไม Fifo บล็อกของคุณtailfเพิ่มวิธีการใช้งานที่ถูกต้อง อันที่จริงวิธีtailfดูเหมือนจะสง่างามกว่า แต่ฉันปล่อยให้ฟีฟ่าด้วยความหวังว่ามันจะมีประโยชน์สำหรับใครบางคน
Dmitry Vasilyanov

การใช้คำตอบ sed ของคุณเพื่อใส่คำอธิบายประกอบในเอาต์พุต vmstat ให้ผลเวลาประทับที่ไม่เปลี่ยนแปลง vmstat 1 | sed -e "s / ^ / $ (วันที่ -R) /"
ChuckCottrill


2

แก้ไขจากคำตอบของ Dmitry Vasilyanov

ใน bash script คุณสามารถเปลี่ยนเส้นทางและล้อมรอบเอาต์พุตด้วยการประทับเวลาทีละบรรทัดได้ทันที

ควรใช้เมื่อใด:

  • สำหรับงานสคริปต์ทุบตีให้แทรกบรรทัดก่อนที่สคริปต์หลัก
  • สำหรับงานที่ไม่ใช่สคริปต์ให้สร้างสคริปต์เพื่อเรียกใช้โปรแกรม
  • สำหรับบริการควบคุมโดยระบบจะดีกว่าที่จะใช้tailfสำหรับล็อกไฟล์ตามที่ Dmitry Vasilyanov กล่าว

ตัวอย่างชื่อ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. ส่วนที่เหลือทำงานเป็น Dmitry Vasilyanov ขยายตัว

ตัวอย่างเช่น:

  • pipe timestamp และบันทึกลงไฟล์

    #!/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
    
  • หรือพิมพ์เวลาประทับและเข้าสู่ระบบเพื่อ stdout

    #!/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วิธีนี้เพื่อรับรายการที่มีการประทับเวลาในบันทึกข้อผิดพลาดสำหรับสคริปต์ที่ฉันใช้เพื่อรับ Cacti ที่เต็มไปด้วยสถิติของโฮสต์ระยะไกล

เพื่อทดสอบ Cacti ฉันใช้randเพื่อเพิ่มค่าสุ่มบางอย่างที่ฉันใช้สำหรับกราฟอุณหภูมิเพื่อตรวจสอบอุณหภูมิระบบของฉัน

Pushmonstats.sh เป็นสคริปต์ที่รวบรวมสถิติอุณหภูมิระบบของพีซีของฉันและส่งไปยัง Raspberry Pi ที่ Cacti ทำงาน เมื่อไม่นานมานี้เครือข่ายติดขัด ฉันมีเวลา SSH เท่านั้นในบันทึกข้อผิดพลาดของฉัน น่าเสียดายที่ไม่มีรายการเวลาในบันทึกนั้น ฉันไม่รู้วิธีเพิ่มการประทับเวลาลงในรายการบันทึก ดังนั้นหลังจากการค้นหาบางบนอินเทอร์เน็ตฉัน stumbled tsเมื่อโพสต์นี้และนี่คือสิ่งที่ผมทำโดยใช้

randเพื่อทดสอบผมใช้เป็นตัวเลือกที่ไม่รู้จักกับ ซึ่งให้ข้อผิดพลาดกับ stderr ในการจับภาพฉันเปลี่ยนเส้นทางไปยังไฟล์ชั่วคราว จากนั้นฉันใช้ cat เพื่อแสดงเนื้อหาของไฟล์และไพพ์ไปยัง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'

บางทีนี่อาจไม่ใช่วิธีที่ยอดเยี่ยมที่จะทำ แต่ใช้งานได้ ฉันสงสัยว่ามีวิธีที่สง่างามกว่านี้หรือไม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.