Yanıtlar:
$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log
Nasıl çalışır:
cat
adlı dosyayı okur input.log
ve 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ı cat
standart girişine yönlendirir sed
.
sed
verileri okur ( cat
ürettiği gibi), işler ( -e
seç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 -R
komut tarafından oluşturulan bir metne değiştirir (replace komutunun genel yapısı:) s/pattern/replace/
.
Sonra göre >>
bash
çıktı sed
bir 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 ... ; done
sonsuz bir döngü çalıştırır ve her yinelemede standart girişine sed
yö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.fifo
fifo dosyasına yönlendirilen standart çıktısına bir ileti yazdırır ve sed
alı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 . sed
Bunu 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 sed
döngü bir nedenden ötürü ölürse - programınız write
birisi read
fifo'dan çıkana kadar dosyaya denendiğinde engellenir .
Yarar, program dosyayı dosyaya yazarken bir iletiye değerlendirilen ve eklenen geçerli zaman damgasıdır.
tailf
Gü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ı tailf
izleyen işlemi çalıştırın bar.raw.log
ve bunları sonsuz while read ... echo
dö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 line
ve 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 tailf
yazmaları 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ı.
tailf
açıkladı, kullanmak için doğru yolu ekledi. Aslında bunun yolu tailf
daha zarif görünüyor, ama birileri için yararlı olacağını umarak fifo yolunu bıraktım.
ts
Perl 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:
tailf
iç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/crontab
ortamda kaydedin
* * * * * root /path-to-script/foo.sh >> /path-to-log-file/foo.log
ts
Bu 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 rand
etmek 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.