2009-01-07 17 views
11

Şu anda stkdr'iBash'ta stderr yönlendirmelerine metin ekle

exec 2>> ${errorLog} 

ile bir hata günlüğüne yeniden yönlendirmek için exec kullanıyorum. Sadece olumsuz olan, her çalıştırmayı zaman damgasıyla başlatmam gerektiğidir çünkü exec sadece metni doğrudan kütük dosyasına iter. Stderr'i yeniden yönlendirmenin bir yolu var mı, ancak zaman damgası gibi bir metin eklememe izin ver.

cevap

16

Bu çok ilginç. Oldukça iyi bash bilen bir adam sordunuz, o da bana böyle anlattı: IFS için atama o kokan yapar iken,

foo() { while IFS='' read -r line; do echo "$(date) $line" >> file.txt; done; }; 

Birincisi, stdin'den ham girişinin bir satır okuyarak bir işlev oluşturur Boşlukları göz ardı etme. Bir satırı okuduktan sonra, hazırlanmış uygun verilerle çıktı. Eğer stderr'e içine yazma

exec 2> >(foo) 

Şimdi herşey foo işlevi aracılığıyla gidecek: Sonra bu işlevin içine stderr'yi yönlendirmek için bash söylemeliyiz. Etkileşimli bir kabukta yaptığınız zaman notu artık görmeyeceksiniz, çünkü stderr'e basıldı ve foo'da okunan satır satır tamponlu :)

+0

$ foo() {while IFS = '' read -r line; echo “$ (date) $ line”> dosya.txt; yapılan; }; $ exec 2>> (foo) Uyarı: '/ bin/bash' programı kilitlendi. whoops – Peter

+0

Ama bunu değiştirirseniz: echo 2 | tee> (foo), o zaman iyi çalışıyor. – Peter

+0

Her satırda önceden açılmış bir dosyaya eklenir. Cevapta, günlük dosyası her satır için açılır. Ve dosyanın sonuna bir arama da gereklidir. Foo'da ikinci bir 'exec' yapmak daha iyi olabilir. – ceving

1

sadece basit kullanabilirsiniz:

exec 1> >(sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1 

Bu tamamen gösterilmemiş İstemi (ITT bir sonraki gösterecektir ilgili e Sorun çözmez bu yazıyı gördükten sonra, ben de umut verici görünüyor başka bir yaklaşım gördü kısa zaman, ama gerçek zamanlı değil, çünkü boru bazı verileri önbelleğe alacaktır ...), ancak 1: 1 çıkışını stdout'ta olduğu gibi dosyada da gösterecektir. O exec ana program için işe yaramaz bir altkabuk açar beri

tek sorun

+0

Bu tüm satırların aynı zaman damgası olsun? – ceving

-1
cat q23123 2> tmp_file ;cat tmp_file | sed -e "s/^/$(date '+[%F %T]'): /g" >> output.log; rm -f tmp_file 
0

Bu ... bir işlevinden bunu yapmak için, ben çözemeyeceği, olduğu örnek, stdout ve stderr'i orijinal stdout ve stderr'i kaybetmeden yeniden yönlendirir. Ayrıca stdout işleyicisindeki hatalar stderr işleyicisine kaydedilir. Dosya tanımlayıcıları değişkenlere kaydedilir ve alt süreçlerde kapatılır. Bash ilgilenir, hiçbir çarpışma olmaz.

#! /bin/bash 

stamp() 
{ 
    local LINE 
    while IFS='' read -r LINE; do 
    echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $$ $LINE" 
    done 
} 

exec {STDOUT}>&1 
exec {STDERR}>&2 
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp) 
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp) 

for n in $(seq 3); do 
    echo loop $n >&$STDOUT 
    echo o$n 
    echo e$n >&2 
done 

Bu günümüzde bu güvenebilirsiniz Shellshock bire bir akım Bash sürümü ama sayesinde gerektirir.