6

現在、大きな (8.1 GB) アクセス ログ ファイルを処理する awk スクリプトを実行していますが、完了するまでに時間がかかります。20 分で、(1000 +- 500)MB の 14MB を書き込みました。

awk スクリプトは次のとおりです。

#!/ビン/バッシュ

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

編集:

awker 以外の場合、スクリプトは各行を読み取り、日付情報を取得し、それをユーティリティdateが認識する形式に変更し、それを呼び出して 1970 年からの秒数として日付を表し、最終的にそれを .csv ファイルの行として返します。 、IP とともに。

入力例: 189.5.56.113 - - [2010/01/22:05:54:55 +0100] "GET (...)"

返される出力: 189.5.56.113,124237889

4

5 に答える 5

13

@OP、あなたのスクリプトは主に、ファイル内のすべての行に対するシステム日付コマンドの過度の呼び出しと、その大きなファイル (GB) が原因で遅くなります。gawk がある場合は、その内部 mktime() コマンドを使用して、日付からエポック秒への変換を行います。

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

出力

$ more file
189.5.56.113 - - [22/Jan/2010:05:54:55 +0100] "GET (...)"
$ ./shell.sh    
189.5.56.113 1264110895
于 2010-01-22T08:28:25.833 に答える
2

本当に速くする必要がある場合は、私がやったことを行うことができます。Ragel を使用して Apache ログ ファイル アナライザーを書き直しました。Ragel では、正規表現を C コードと組み合わせることができます。正規表現は非常に効率的な C コードに変換され、コンパイルされます。残念ながら、これには C でコードを書くのに非常に慣れている必要があります。私はもうこのアナライザーを持っていません。1 ~ 2 秒で 1 GB の Apache アクセス ログを処理しました。

awk ステートメントから不要な printfs を削除し、それらをより単純なものに置き換えることに成功する可能性は限られています。

于 2010-01-22T04:36:27.223 に答える
2

を使用している場合はgawk、日付と時刻をmktime(gawk関数が) 理解できる形式に変換できます。現在使用しているのと同じタイムスタンプが提供され、繰り返しsystem()呼び出しのオーバーヘッドが節約されます。

于 2010-01-22T05:45:26.270 に答える
2

この小さな Python スクリプトは、約 200MB の出力を生成する私のマシンで約 3 分でサンプル行の約 400MB 相当のコピーを処理します (サンプル行が非常に短いことに注意してください。これはハンディキャップです)。

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()

小さな問題は、タイムゾーンを処理しないことです (strptime() 問題) が、それをハードコードするか、それを処理するために少し余分に追加することができます。

しかし、正直なところ、これほど単純なものは、C で簡単に書き直せるはずです。

于 2010-01-22T05:51:16.867 に答える
1
gawk '{
    dt=substr($4,2,11); 
    gsub(/\//," ",dt); 
    "date -d \""dt"\" +%s"|getline ts; 
    print $1, ts
}' yourfile
于 2013-06-07T13:51:59.247 に答える