Menambahkan cap stempel waktu bersama dengan baris file log


11

Saya memiliki file log dan saya perlu menambahkan cap waktu untuk setiap baris saat mereka ditambahkan. Jadi saya sedang mencari skrip yang menambahkan cap waktu untuk setiap entri dalam baris log dan yang dapat dijalankan sebagai pekerjaan cron.

Jawaban:


18

Cara Umum

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

Bagaimana itu bekerja:

  1. catmembaca file yang dipanggil input.logdan hanya mencetaknya ke aliran output standar.

    Biasanya output standar terhubung ke terminal, tetapi skrip kecil ini berisi |sehingga shell mengarahkan output catstandar ke input standar sed.

  2. sedmembaca data (saat catmemproduksinya), memprosesnya (sesuai dengan skrip yang disediakan dengan -eopsi) dan kemudian mencetaknya ke output standar. Skrip "s/^/$(date -R) /"berarti mengganti setiap awal baris ke teks yang dihasilkan oleh date -Rperintah (konstruksi umum untuk perintah ganti adalah:) s/pattern/replace/.

  3. Kemudian sesuai dengan >> bashpengalihan output sedke file bernama output.log( >berarti ganti konten file dan >>berarti tambahkan sampai akhir).

Masalahnya adalah $(date -R)dievaluasi satu kali ketika Anda menjalankan skrip sehingga akan memasukkan cap waktu saat ini ke awal setiap baris. Stempel waktu saat ini mungkin jauh dari saat ketika pesan dihasilkan. Untuk menghindarinya, Anda harus memproses pesan sebagaimana ditulis ke file, bukan dengan tugas cron.

FIFO

Pengalihan aliran standar yang dijelaskan di atas disebut pipa . Anda dapat mengarahkan ulang tidak hanya dengan |antara perintah dalam skrip, tetapi melalui file FIFO (alias pipa bernama ). Satu program akan menulis ke file dan yang lain akan membaca data dan menerimanya sebagai yang pertama dikirim.

Pilih sebuah contoh:

$ 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

Bagaimana itu bekerja:

  1. mkfifo menciptakan pipa bernama

  2. while true; do sed ... ; donemenjalankan loop tak terbatas dan pada setiap iterasi ia berjalan seddengan mengarahkan ulang foo.log.fifoke input standarnya; sed blok menunggu input data dan kemudian memproses pesan yang diterima dan mencetaknya ke output standar diarahkan ke foo.log.

    Pada titik ini Anda harus membuka jendela terminal baru karena loop menempati terminal saat ini.

  3. echo ... > foo.log.fifomencetak pesan ke output standarnya yang dialihkan ke file fifo dan sedmenerimanya serta memproses dan menulis ke file biasa.

Catatan penting adalah fifo sama seperti pipa lain tidak masuk akal jika salah satu sisinya tidak terhubung ke proses apa pun. Jika Anda mencoba menulis ke pipa, proses saat ini akan memblokir sampai seseorang akan membaca data di sisi lain pipa. Jika Anda ingin membaca dari sebuah pipa proses akan memblokir sampai seseorang akan menulis data ke pipa. The sedloop dalam contoh di atas tidak apa-apa (tidur) sampai Anda lakukan echo.

Untuk situasi khusus Anda, Anda cukup mengkonfigurasi aplikasi Anda untuk menulis pesan log ke file fifo. Jika Anda tidak dapat mengonfigurasinya - cukup hapus file log asli dan buat file fifo. Tetapi perhatikan lagi bahwa jika sedloop akan mati karena suatu alasan - program Anda akan diblokir saat mencoba ke writefile sampai seseorang akan readdari fifo.

Manfaatnya adalah cap waktu saat ini dievaluasi dan dilampirkan ke pesan ketika program menulisnya ke file.

Pemrosesan Asynchronous Dengan tailf

Untuk membuat penulisan ke log dan pemrosesan lebih mandiri, Anda dapat menggunakan dua file biasa tailf. Aplikasi akan menulis pesan ke file mentah dan proses lain membaca baris baru (ikuti untuk menulis secara tidak sinkron) dan memproses data dengan menulis ke file kedua.

Mari kita ambil contoh:

# 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

Bagaimana itu bekerja:

  1. Jalankan tailfproses yang akan mengikuti tulis bar.raw.logdan cetak ke output standar yang dialihkan ke while read ... echoloop tak terbatas . Loop ini melakukan dua tindakan: membaca data dari input standar ke variabel buffer yang disebut linedan kemudian menulis timestamp yang dihasilkan dengan data buffered berikut ke bar.log.

  2. Tulis beberapa pesan ke bar.raw.log. Anda harus melakukan ini di jendela terminal terpisah karena yang pertama akan ditempati oleh tailfyang akan mengikuti penulisan dan melakukan tugasnya. Cukup sederhana.

Pro adalah aplikasi Anda tidak akan diblokir jika Anda membunuh tailf. Kontra adalah cap waktu yang kurang akurat dan duplikat file log.


Terima kasih .Fifo tampaknya sangat tepat untuk saya gunakan. Program saya sudah menulis di log file.txt tetapi file ini perlu diarahkan ke foo.log.fifo.Tapi melakukan $ tailf file.txt> foo.log.fifo hang ! Jadi bagaimana saya bisa mengarahkan ulang konten saya dalam file log yang diperbarui ke foo.log.fifo ini sehingga bisa menambahkan waktu juga.
Kratos

Baru saja memperbaiki jawabannya. Dijelaskan mengapa fifo memblokir Anda tailf, menambahkan cara yang tepat untuk menggunakannya. Sebenarnya cara dengan tailftampaknya lebih elegan, tetapi saya meninggalkan cara fifo dengan harapan itu akan bermanfaat bagi seseorang.
Dmitry Vasilyanov

Menggunakan jawaban sed Anda untuk membubuhi keterangan keluaran vmstat menghasilkan stempel waktu yang tidak berubah, vmstat 1 | sed -e "s / ^ / $ (date -R) /"
ChuckCottrill


2

Dimodifikasi dari jawaban Dmitry Vasilyanov.

Dalam skrip bash, Anda dapat mengarahkan dan membungkus output dengan timestamp baris demi baris dengan cepat.

Kapan harus menggunakan:

  • Untuk pekerjaan skrip bash, masukkan baris sebelum skrip utama
  • Untuk pekerjaan non-skrip, buat skrip untuk memanggil program.
  • Untuk kontrol layanan oleh sistem, lebih baik digunakan tailfuntuk file log seperti kata Dmitry Vasilyanov.

Contoh bernama 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"

Dan hasilnya:

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

Bagaimana itu bekerja

  1. exec &> Redirect stdout dan stderr ke tempat yang sama
  2. >( ... ) output pipa ke perintah dalam asinkron
  3. Bagian sisanya berfungsi ketika Dmitry Vasilyanov diperluas.

Sebagai contoh:

  • stempel waktu pipa dan masuk ke file

    #!/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
    
  • Atau cetak stempel waktu dan masuk ke 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
    

    lalu simpan dalam /etc/crontabpengaturan

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

1

Saya menggunakan tscara ini untuk mendapatkan entri dengan cap waktu di log kesalahan untuk skrip yang saya gunakan untuk membuat Cacti diisi dengan statistik host jarak jauh.

Untuk menguji Cacti saya gunakan randuntuk menambahkan beberapa nilai acak yang saya gunakan untuk grafik suhu untuk memonitor suhu sistem saya.

Pushmonstats.sh adalah skrip yang mengumpulkan statistik suhu sistem PC saya dan mengirimkannya ke Raspberry Pi tempat Cacti beroperasi. Beberapa waktu lalu, jaringannya macet. Saya hanya mendapat SSH time out di log kesalahan saya. Sayangnya, tidak ada entri waktu dalam log itu. Saya tidak tahu cara menambahkan cap waktu ke entri log. Jadi, setelah beberapa pencarian di Internet, saya menemukan posting ini dan inilah yang saya gunakan ts.

Untuk mengujinya, saya menggunakan opsi yang tidak diketahui rand. Yang memberi kesalahan pada stderr. Untuk menangkapnya, saya mengarahkannya ke file sementara. Kemudian saya menggunakan cat untuk menunjukkan isi file dan mengirimnya ke pipa ts, menambahkan format waktu yang saya temukan di posting ini dan akhirnya log ke file kesalahan. Lalu saya menghapus isi dari file sementara, kalau tidak saya mendapatkan entri ganda untuk kesalahan yang sama.

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

Ini memberikan yang berikut di log kesalahan saya:

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

Mungkin ini bukan cara yang sangat elegan untuk melakukannya, tetapi berhasil. Saya bertanya-tanya apakah ada pendekatan yang lebih elegan untuk itu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.