Yanıtlar:
$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log
Nasıl çalışır:
catadlı dosyayı okur input.logve standart çıktı akışına yazdırır.
Normalde standart çıkış bir terminale bağlanır, ancak bu küçük komut dosyası, |kabuğun standart çıkışını catstandart girişine yönlendirir sed.
sedverileri okur ( catürettiği gibi), işler ( -eseçenekle birlikte sağlanan komut dosyasına göre ) ve sonra standart çıktısına yazdırır. Komut dosyası "s/^/$(date -R) /", satırın her başlangıcını date -Rkomut tarafından oluşturulan bir metne değiştirir (replace komutunun genel yapısı:) s/pattern/replace/.
Sonra göre >> bashçıktı sedbir dosyaya yönlendirir output.log( >dosya içeriğini değiştirmek >>anlamına gelir ve sonuna sonuna anlamına gelir).
$(date -R)Komut dosyasını çalıştırdığınızda, her satırın başına geçerli zaman damgasını ekleyecek şekilde sorun bir kez değerlendirilir . Geçerli zaman damgası, bir iletinin oluşturulduğu andan çok uzakta olabilir. Bunu önlemek için iletileri bir cron işi ile değil, dosyaya yazılırken işlemeniz gerekir.
Yukarıda açıklanan standart akım yönlendirmesi boru olarak adlandırılır . Yalnızca |komut dosyasındaki komutlar arasında değil, bir FIFO dosyası aracılığıyla da adlandırılır (pip adı da verilir ). Bir program dosyaya yazar ve diğeri verileri okur ve ilk gönderilirken alır.
Bir örnek seçin:
$ 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
Nasıl çalışır:
mkfifo adlandırılmış bir kanal oluşturur
while true; do sed ... ; donesonsuz bir döngü çalıştırır ve her yinelemede standart girişine sedyönlendirerek çalışır foo.log.fifo; sed giriş verilerinin beklemesini engeller ve daha sonra alınan bir mesajı işler ve yönlendirilen standart çıkışa yazdırır foo.log.
Bu noktada, döngü geçerli terminali işgal ettiğinden yeni bir terminal penceresi açmanız gerekir.
echo ... > foo.log.fifofifo dosyasına yönlendirilen standart çıktısına bir ileti yazdırır ve sedalır ve işler ve normal bir dosyaya yazar.
Önemli not, kenarlarından biri herhangi bir işleme bağlı değilse diğer boruların hiçbir anlamı olmadığı için fifo'dur. Bir boruya yazmaya çalışırsanız, geçerli işlem birisi borunun diğer tarafındaki verileri okuyana kadar engellenir . Bir kanaldan okumak istiyorsanız, birisi boruya veri yazana kadar işlem engellenir . sedBunu yapana kadar örnekte döngü üstünde bir şey (uyur) yapar echo.
Özel durumunuz için uygulamanızı fifo dosyasına günlük mesajları yazacak şekilde yapılandırmanız yeterlidir. Yapılandıramıyorsanız - orijinal günlük dosyasını silin ve bir fifo dosyası oluşturun. Ancak tekrarlayın, eğer seddöngü bir nedenden ötürü ölürse - programınız writebirisi readfifo'dan çıkana kadar dosyaya denendiğinde engellenir .
Yarar, program dosyayı dosyaya yazarken bir iletiye değerlendirilen ve eklenen geçerli zaman damgasıdır.
tailfGünlüğe yazmayı ve işlemeyi daha bağımsız hale getirmek için iki normal dosya kullanabilirsiniz tailf. Bir uygulama ham bir dosyaya mesaj yazacak ve diğer işlemler yeni satırları okuyacaktır (eşzamansız olarak yazmaları takip edin) ve verileri ikinci dosyaya yazarak işleyecektir.
Bir örnek verelim:
# 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
Nasıl çalışır:
Yazmaları tailfizleyen işlemi çalıştırın bar.raw.logve bunları sonsuz while read ... echodöngüye yönlendirilen standart çıktıya yazdırın . Bu döngü iki eylem gerçekleştirir: standart girişten veri adlı bir tampon değişkenine veri okuyun lineve ardından aşağıdaki tamponlanmış verilerle oluşturulan zaman damgasını yazın bar.log.
Adresine bazı mesajlar yazın bar.raw.log. Bunu ayrı bir terminal penceresinde yapmak zorundasınız, çünkü ilki tailfyazmaları takip edecek ve işini yapacak. Oldukça basit.
Artıları, öldürürseniz uygulamanızın engellemeyeceğidir tailf. Eksileri daha az doğru zaman damgaları ve yinelenen günlük dosyaları.
tailfaçıkladı, kullanmak için doğru yolu ekledi. Aslında bunun yolu tailfdaha zarif görünüyor, ama birileri için yararlı olacağını umarak fifo yolunu bıraktım.
tsPerl betiğini şuradan kullanabilirsiniz moreutils:
$ echo test | ts %F-%H:%M:%.S
2012-11-20-13:34:10.731562 test
Dmitry Vasilyanov'un cevabından değiştirildi.
Bh komut dosyasında, çıkışı zaman damgası ile satır satır satır yönlendirebilir ve sarabilirsiniz.
Ne zaman kullanılır:
tailfiçin, Dmitry Vasilyanov'un dediği gibi günlük dosyası için kullanmak daha iyidir .Adlı bir örnek 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"
Ve sonuç:
$ bash foo.sh
$ cat foo.log
May 12 20:04:11 foo
May 12 20:04:12 bar
May 12 20:04:13 foobar
Nasıl çalışır
exec &> Stdout ve stderr'ı aynı yere yönlendirin>( ... ) asenkron iç komuta boru çıkışlarıÖrneğin:
boru zaman damgası ve günlük dosyası
#!/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
Veya zaman damgasını yazdırın ve stdout'a giriş yapın
#!/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
sonra onları /etc/crontabortamda kaydedin
* * * * * root /path-to-script/foo.sh >> /path-to-log-file/foo.log
tsBu yolu, Cacti'nin uzak bir ana bilgisayarın istatistikleriyle doldurmasını sağlamak için kullandığım bir komut dosyasının hata günlüğünde bir zaman damgası içeren bir giriş almak için kullanılır .
Kaktüsleri test randetmek için, sistemlerimin sıcaklığını izlemek amacıyla sıcaklık grafikleri için kullandığım bazı rastgele değerler eklemek için kullanıyorum.
Pushmonstats.sh, bilgisayarımın sistem sıcaklığı istatistiklerini toplayan ve bunu Cacti'nin çalıştığı bir Raspberry Pi'ye gönderen bir komut dosyasıdır. Bir süre önce, ağ sıkışmıştı. Hata günlüğümde yalnızca SSH zaman aşımları var. Ne yazık ki, bu günlükte zaman girişi yok. Bir günlük girişine nasıl zaman damgası ekleyeceğimi bilmiyordum. Yani, internette yapılan bazı aramalardan sonra, bu yazıyı tökezledim ve bunu kullanarak yaptım ts.
Test etmek için bilinmeyen bir seçenek kullandım rand. Hangi stderr bir hata verdi. Yakalamak için geçici bir dosyaya yönlendiriyorum. Sonra cat içeriğini kullanarak dosyanın içeriğini göstermek ve pipo ts, bu yazı bulduğum bir zaman biçimi eklemek ve nihayet hata dosyasına oturum. Daha sonra geçici dosyanın içeriğini temizlerim, aksi takdirde aynı hata için çift giriş alırım.
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
Bu, hata günlüğümde aşağıdakileri verir:
2014-03-22-19:17:53.823720 rand: unknown option -- '-l'
Belki de bunu yapmanın çok zarif bir yolu değil, ama işe yarıyor. Daha zarif bir yaklaşım olup olmadığını merak ediyorum.