はじめに
powershellの正規表現を使って、ログの一部の情報だけを抽出・整形して表示したい。
ここでは、apacheのアクセスログを題材として、
特定のIPからのリクエストに関するサマリを表示できることを目標にする。
↓これが
access_log
123.123.123.123 - - [24/Feb/2022:10:03:34 +0000] "GET /favicon.ico HTTP/1.1" 404 196 "http://999.999.999.999:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
↓こうなるのが目標
PS > .\extract.ps1 .\logs\access_log 123.123.123.123
IP : 123.123.123.123
Date : 24/Feb/2022:10:03:34 +0000
Request : GET /favicon.ico HTTP/1.1
StatusCode : 404
Size : 196
URL : http://999.999.999.999:8080/
方針
apacheのaccess_logは、デフォルトでは以下のような形式で出力される。下の場合、左から順に、
- 接続元のIP :
123.123.123.123
- アクセス時刻 :
[24/Feb/2022:10:03:34 +0000]
- リクエストの詳細 :
"GET /favicon.ico HTTP/1.1"
- ステータスコード : 404
- 送信したデータ量 : 196
- URL : "http://999.999.999.999:8080/"
- OS・ブラウザの情報:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
が記載されている。
/var/log/httpd/access_log
123.123.123.123 - - [24/Feb/2022:10:03:34 +0000] "GET /favicon.ico HTTP/1.1" 404 196 "http://999.999.999.999:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
上記を以下のパターンでマッチングさせる。
(?<IP>^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)
のように、()
で括って?<IP>
と名前を付けておくと、後からその名前で取り出すことができる。
Pattern
(?<IP>^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*\[(?<Date>.*)\] \"(?<Request>.*)\" (?<StatusCode>[0-9]+) (?<Size>[0-9]+) \"(?<URL>.*)\"
詳細は以下を参照。
- 正規表現について - PowerShell
- ログファイル - Apache HTTP サーバ バージョン 2.4
実装
①access_logから情報を抽出するpowershellスクリプトextract.ps1
を書く
折角<?IP>
のように名前を付けているのだが、なぜか$_.Matches.Groups["IP"].value
と書くことはできず、
仕方なくインデックスで取っている。
※一応$_.Matches.Groups[1].Nameには「IP」という文字列が格納されているようだ
extract.ps1
Param(
[String]$filepath,
[String]$IPaddr
)
$Pattern = '(?<IP>' + $IPaddr + ').*\[(?<Date>.*)\] \"(?<Request>.*)\" (?<StatusCode>[0-9]+) (?<Size>[0-9]+) \"(?<URL>.*)\" '
# $Pattern '(?<IP>^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*\[(?<Date>.*)\] \"(?<Request>.*)\" (?<StatusCode>[0-9]+) (?<Size>[0-9]+) \"(?<URL>.*)\" '
Select-String -Pattern $Pattern $filepath | ForEach-Object {
$IP = $_.Matches.Groups[1].value
$Date = $_.Matches.Groups[2].value
$Request = $_.Matches.Groups[3].value
$StatusCode = $_.Matches.Groups[4].value
$Size = $_.Matches.Groups[5].value
$URL = $_.Matches.Groups[6].value
Write-Output "IP : $IP"
Write-Output "Date : $Date"
Write-Output "Request : $Request"
Write-Output "StatusCode : $StatusCode"
Write-Output "Size : $Size"
Write-Output "URL : $URL"
Write-Output ""
}
②サンプルになるアクセスログを用意する
一つだけ123.123.123.123
からのアクセスが紛れ込んでおり、この情報を抽出したい。
access_log
111.111.111.111 - - [24/Feb/2022:10:01:45 +0000] "GET / HTTP/1.1" 200 12976 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
111.111.111.111 - - [24/Feb/2022:10:01:45 +0000] "GET /Carousel%20Template%20%E3%83%BB%20Bootstrap%20v5.0_files/bootstrap.bundle.min.js.%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89 HTTP/1.1" 404 196 "http://999.999.999.999/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
111.111.111.111 - - [24/Feb/2022:10:01:45 +0000] "GET /files/carousel.css HTTP/1.1" 200 1695 "http://999.999.999.999/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
111.111.111.111 - - [24/Feb/2022:10:01:45 +0000] "GET /files/bootstrap.min.css HTTP/1.1" 200 155845 "http://999.999.999.999/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
111.111.111.111 - - [24/Feb/2022:10:03:34 +0000] "GET / HTTP/1.1" 200 10 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
123.123.123.123 - - [24/Feb/2022:10:03:34 +0000] "GET /favicon.ico HTTP/1.1" 404 196 "http://999.999.999.999:8080/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
111.111.111.111 - - [24/Feb/2022:10:03:37 +0000] "GET /Carousel%20Template%20%E3%83%BB%20Bootstrap%20v5.0_files/bootstrap.bundle.min.js.%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89 HTTP/1.1" 404 196 "http://999.999.999.999/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
③実行
extract.ps1
の引数にログのパスとIPアドレスを指定して実行する。
うまく情報が抽出できていることがわかる。
PS > .\extract.ps1 .\logs\access_log 123.123.123.123
IP : IP
Date : 24/Feb/2022:10:03:34 +0000
Request : GET /favicon.ico HTTP/1.1
StatusCode : 404
Size : 196
URL : http://999.999.999.999:8080/
おわりに
- 実際にはlinuxサーバ上にあるapacheのログをpowershellで扱うことはまずないため、このスクリプトが日の目を浴びる機会はそうそうない・・・。サーバ上でawkとかでやることになると思われる。
-
折角
のように名前を付けているのだが、なぜか$_.Matches.Groups["IP"].valueと書くことはできず、 仕方なくインデックスで取っている
の件、うまい書き方ご存じの方いたらぜひ教えてください。。。