2010-01-22 25 views
5

Şu anda büyük (8.1GB) bir erişim günlüğü dosyasını işlemek için bir awk komut dosyası çalıştırıyorum ve bitmek için sonsuza dek sürüyor. 20 dakika içinde, yazmayı beklediğim 14MB (1000 + - 500) MB yazdı ve bir şekilde daha hızlı işleyebilir miyim diye merak ediyorum. İşte Apache'nin işlenmesi hızlı bir şekilde günlüğe kaydediyor

awk script:

 
#!/bin/bash 

awk '{t=$4" "$5; gsub("[\[\]\/]"," ",t); sub(":"," ",t);printf("%s,",$1);system("date -d \""t"\" +%s");}' $1 

DÜZENLEME: olmayan awkers için

, senaryo, her satırı okur tarih bilgilerini alır, bir biçime değiştirir date programı, tarihi 1970’ten bu yana saniye olarak gösteren ve IP ile birlikte bir .csv dosyasının satırı olarak döndüren tarihi tanımak ve çağırır.

Örnek girişi: 189.5.56.113 - - [22// 2010 Ocak: 05: 54: 55 0100] "(...) GET"

İade çıkışı: 189.5.56.113, 124237889

+2

Belki senaryo bize böylece olmayan awkers ne yaptığını anlatabilir misiniz Başka bir dilde daha hızlı bir yazı yazabilir mi?Yine de, bir bakışta, sisteme() her yeni kayıtta yeni bir işlem oluşturmanın oldukça yavaş olması gerekir. –

cevap

11

@OP, senaryonuz esas yavaş yeniden yazmak gibi kolay olmalı dosya ve onun büyük bir dosya (GB). Eğer gawk varsa, saniye dönüşüme Epoch'tan tarih yapmak iç mktime() komutunu kullanın

awk 'BEGIN{ 
    m=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",d,"|") 
    for(o=1;o<=m;o++){ 
     date[d[o]]=sprintf("%02d",o) 
    } 
} 
{ 
    gsub(/\[/,"",$4); gsub(":","/",$4); gsub(/\]/,"",$5) 
    n=split($4, DATE,"/") 
    day=DATE[1] 
    mth=DATE[2] 
    year=DATE[3] 
    hr=DATE[4] 
    min=DATE[5] 
    sec=DATE[6] 
    MKTIME= mktime(year" "date[mth]" "day" "hr" "min" "sec) 
    print $1,MKTIME 

}' file 

çıkış

$ more file 
189.5.56.113 - - [22/Jan/2010:05:54:55 +0100] "GET (...)" 
$ ./shell.sh  
189.5.56.113 1264110895 
+0

Sistem() çağrısının kaldırılması programımı 10 kat daha hızlı yaptı! – konr

2

Gerçekten daha hızlı olmanıza gerçekten ihtiyacınız varsa, yaptığım şeyi yapabilirsiniz. Ragel kullanarak bir Apache log dosyası analizcisini yeniden yazdım. Ragel, düzenli ifadeleri C koduyla karıştırmanıza izin verir. Normal ifadeler çok verimli C koduna dönüştürülür ve sonra derlenir. Ne yazık ki, bu sizin için çok rahat C içinde yazma kodu gerektirir. Artık bu analiz cihazına sahip değilim. 1 GB Apache erişim kayıtlarını 1 veya 2 saniye içinde işledi.

Gereksiz yazdırma öğelerini awk ifadenizden kaldırmak ve bunları daha basit bir şeyle değiştirmek konusunda sınırlı başarı elde edebilirsiniz.

2

gawk10 kullanıyorsanız, tarih ve saatinizi mktime (gawk işlevinin) anladığı bir formata masaj yapabilirsiniz. Şimdi kullanmakta olduğunuz aynı zaman damgasını verecek ve tekrarlanan system() çağrılarının genel giderlerini kaydedeceksiniz. (Bunun bir engel yüzden, örnek hattı oldukça kısaydı unutmayın)

2

Bu küçük Python komut ~ üreten benim makinede yaklaşık 3 dakika içinde çıkış 200MB senin örneğin hattının kopya ~ 400MB değerinde ele alır:

import time 

src = open('x.log', 'r') 
dest = open('x.csv', 'w') 

for line in src: 
    ip = line[:line.index(' ')] 
    date = line[line.index('[') + 1:line.index(']') - 6] 
    t = time.mktime(time.strptime(date, '%d/%b/%Y:%X')) 
    dest.write(ip) 
    dest.write(',') 
    dest.write(str(int(t))) 
    dest.write('\n') 

src.close() 
dest.close() 

Küçük bir sorun, zaman dilimlerinin (strptime() problemi) ele alınmamasıdır, ancak bunu düzeltmek ya da bunlara dikkat etmek için biraz fazladan ekleyebilirsiniz.

Ama dürüst olmak gerekirse, bu kadar basit bir şey yüzünden her satır için sistem tarihi komutunun aşırı çağrısına C.

1
gawk '{ 
    dt=substr($4,2,11); 
    gsub(/\//," ",dt); 
    "date -d \""dt"\" +%s"|getline ts; 
    print $1, ts 
}' yourfile 
İlgili konular