私のApacheログファイルにはother_vhosts_access.log
次のようなものがあります。
www.example.com:80 12.34.56.78 - - [01/Aug/2017:00:42:18 +0200] "GET /page1.html HTTP/1.1" 200 1542 " "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
www.example.com:80 99.99.99.99 - - [02/Aug/2017:06:19:44 +0200] "GET /test.jpg HTTP/1.1" 200 90749 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
www.anotherwebsite.com:80 11.11.11.11 - - [04/Aug/2017:09:39:01 +0200] "GET /test.jpg HTTP/1.1" 200 90749 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
...
www.example.com:80 12.34.56.78 - - [23/Aug/2017:01:12:11 +0200] "GET /somethingelse2.html HTTP/1.1" 200 21161 "http://www.example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
訪問した訪問者を探したいです。/page1.html
そして /somethingelse2.html
、この例では12.34.56.78です。
私が使用している場合:
grep page1.html other_vhosts_access.log
残りの行にはが含まれていないため、出力をフィルタリングすることはできませんsomethingelse2.html
。
特定のページ+他のページを訪問した訪問者をどのように見つけることができますか?
答え1
bash
、grep
およびawk
:を使用してください。
page1.html
ファイルに関連するすべてのIP番号を取得する方法は次のとおりです。
awk '/page1\.html/ { print $2 }' log
たとえば、データが出力されます12.34.56.78
。
これは、そのIPアドレスを含むすべてのログエントリを取得するために使用できます。
grep -wF -f <( awk '/page1\.html/ { print $2 }' log ) log
これはコマンドの結果をawk
パターンとして使用し、ログファイルを再スキャンしてそのIPを含むすべての行を出力します。これにより、例の最初の行と最後の行が返されます。
フラグは、次のように解釈されるパターン(IPアドレス)を-w
知らせるために使用されます。-F
grep
grep
固定文字列(-F
)これを含む文字列のみを返します。フルワード(-w
)。これは12.34.56.789
、固定文字列パターンが一致しないことを意味します12.34.56.78
。
この結果から、削除するpage1.html
ラインについて
grep -wF -f <( awk '/page1\.html/ { print $2 }' log ) log | grep -vF 'page1.html'
これで、ページ訪問者によって生成されたすべてのログエントリがあります(ページ自体page1.html
ではありません)。page1.html
特定のプロジェクトのアイテムを入手するには特別な別のページを選択し、最後のページgrep -vF 'page1.html'
をgrep -F 'otherpage.html'
。
より強力なログ解析と分析ツールがあると確信していますが、あるとしてもよくわかりません(私はログ解析を頻繁に行いません)。
答え2
通常、これは入力から見たものを記憶するために連想配列を使用してawkで行われます。デフォルトの awk スペースフィールド区切り文字を使用すると、フィールド 2 が IP アドレスであり、フィールド 8 が URL であることがわかります。たとえば、次のようになります。
awk '$8=="/page1.html" { ipaddr[$2] = 1; next }
$8=="/somethingelse2.html" { if(ipaddr[$2]==1)print $2 }'
これは url フィールドを比較し、最初の url と一致すると、配列のipaddr
IP アドレスのエントリを生成し、値 1 を保持します。 2番目のURLと一致する場合は、そのエントリが同じIPアドレスに設定されていることを確認し、そうであれば印刷します。同じIPアドレスを再印刷したくない場合は、別のアレイに書き込むことができます。
awk '$8=="/page1.html" { ipaddr[$2] = 1; next }
$8=="/somethingelse2.html" { if(ipaddr[$2]==1 && !done[$2]){print $2; done[$2]=1 } }'
URLにクエリ部分(たとえば"/page1.html?id=77"
)がある場合は、比較の代わりに一致を使用できます$8~/^\/page1.html/
。
逆の順序でURLにアクセスできる場合は、ビットマスク値を使用して既に見た値(ページ1の場合は1、他の項目2の場合は2)を覚えてから、値3が取得されるのを待つことができます。ビットマスクは、or
および同じ機能を介してのみawkで使用できますand
。だから私たちは
awk '
BEGIN { v["/page1.html"] = 1
v["/somethingelse2.html"] = 2
}
$8=="/page1.html" || $8=="/somethingelse2.html" {
ipaddr[$2] = or(ipaddr[$2], v[$8])
if(ipaddr[$2]==3){ print $2; ipaddr[$2] = 4 }
}'
v
これは、URLをビットマスク値(整数)に変換するために最初に実行されたBEGINブロックの連想配列にマッピングを設定します。 URLが一致すると、記憶された値は適切なビットマスク値または-edを持ちます。これで3の場合は、そのアドレスを印刷して再印刷しないように設定します。
答え3
これを実行している間、other_vhosts_access.logの形式が思ったよりも多様であることがわかります。たとえば、お気に入りの列の一部を選択してawk '{print $2, $8}' other_vhosts_access.log > small.log
から、より簡単に観察できるようにsmall.logで作業することをお勧めします。
問題の説明はhttps://httpd.apache.org/docs/2.4/logs.html:
...一般的に使用される形式文字列は、結合ログ形式と呼ばれます。次のように使用できます。 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{おすすめ}i\" \"%{ユーザー エージェント}i\"" の組み合わせ
これを使っているようです。 (削除された)ログでこれを参照しています。example.com
これは、example.comなどのサイトにあなたのサイトを指すHREFがあり、ブラウザのGETリクエストに「Referer:www.example.com」ヘッダーが含まれていることを示します。
/page1には/page2のHREFがあるようです。一部のブラウザは、page2要求時にpage1リファラーヘッダーを送信します。これに依存し、「page2.*page1」にgrepを選択できます。または、許可された回答に示すように送信元IPを使用することを選択できます。この場合、誤った一致を引き起こす他の邪魔になる熱を取り除き、分析に単純化されたsmall.logを使用できます。