Windows Server 2012いいですね!もう2008R2以前に戻れません。
さて、IISですが、相変わらず読みにくいログです…。
今回、接続元のIPをログから取得、調査するする必要に迫られたので、スクリプトを書きました。
せっかくなので公開しておきます。
IISのログ場所
デフォルトのログ保存パスは以下です。
C:\inetpub\logs\LogFiles\W3SVC1\
ここに以下のファイル名規則でログが保持されています。
u_exYYMMdd.log
Git公開
コードはGitで公開しています。
最新は此処から取得してください。
https://github.com/guitarrapc/PowerShellUtil/tree/master/Get-IisLogFileCIps
コード全文
最新はGitを参照してください。(※このコードはApt/18/2013時点のものです。)
ログファイルの日付指定とか、もう少し改修が欲しいですね (記事書いてて思ったので
近日更新をしましょう。
19/Apr/2013 更新しました。
#Requires -Version 3.0
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none",
DefaultParameterSetName = "ExportAsCsv"
)]
param
(
[Parameter(
HelpMessage = "Input Path of IIS Log file. Default : C:\inetpub\logs\LogFiles\W3SVC1\",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[string]
$IISLogPath = "C:\inetpub\logs\LogFiles\W3SVC1\",
[Parameter(
HelpMessage = "Input Suffix of IIS Log file. Default : u_ex",
Position = 1,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[string]
$IISLogFileHead = "u_ex",
[Parameter(
HelpMessage = "Input date of IIS Log file . Default : `"`"",
Position = 2,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[string]
$IISLogFileDate = "",
[Parameter(
HelpMessage = "Input Extention of IIS Log file. Default : .log",
Position = 3,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[string]
$IISLogFileExtention = ".log",
[Parameter(
HelpMessage = "Select switch if you want to output with sort all AddressList to Unique. Default : Not Selected",
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[switch]
$sortUniq,
[Parameter(
HelpMessage = "If you select this switch, output with csv. Default selected",
Mandatory = $false,
ParameterSetName="ExportAsCsv"
)]
[switch]
$ExportAsCsv,
[Parameter(
HelpMessage = "If you select this switch, output with json. Default not selected",
Mandatory = $false,
ParameterSetName="ExportAsJson"
)]
[switch]
$ExportAsJson
)
function Get-IisLogFileCIps{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none",
DefaultParameterSetName = "ExportAsCsv"
)]
param
(
[Parameter(
HelpMessage = "Input Path of IIS Log file. Default : C:\inetpub\logs\LogFiles\W3SVC1\",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[string]
$IISLogPath = "C:\inetpub\logs\LogFiles\W3SVC1\",
[Parameter(
HelpMessage = "Input Suffix of IIS Log file. Default : u_ex",
Position = 1,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[string]
$IISLogFileHead = "u_ex",
[Parameter(
HelpMessage = "Input date of IIS Log file . Sample : `'2013/04/17`'",
Position = 2,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[string]
$IISLogFileDate = "",
[Parameter(
HelpMessage = "Input Extention of IIS Log file. Default : .log",
Position = 3,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[string]
$IISLogFileExtention = ".log",
[Parameter(
HelpMessage = "Select switch if you want to output with sort all AddressList to Unique. Default : Not Selected",
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[switch]
$sortUniq,
[Parameter(
HelpMessage = "If you select this switch, output with csv. Default selected",
Mandatory = $false,
ParameterSetName="ExportAsCsv"
)]
[switch]
$ExportAsCsv,
[Parameter(
HelpMessage = "If you select this switch, output with json. Default not selected",
Mandatory = $false,
ParameterSetName="ExportAsJson"
)]
[switch]
$ExportAsJson
)
begin
{
$prevstatus = $true
}
process
{
# Check IIS Log file exit or not, when $IISLogFileDate had passed
if($IISLogFileDate -ne "")
{
# Cast and Perse $IISLogFileDate to use for filename
$IISLogFileDate = ([datetime]$IISLogFileDate).ToString("yyMMdd")
$IISLogFileName = ($IISLogFileHead + $IISLogFileDate + $IISLogFileExtention)
$IISLogFullPath = Join-Path $IISLogPath $IISLogFileName
if(!(Test-Path $IISLogFullPath))
{
throw "$IISLogFileDate format was correct. But $IISLogFullPath not found. Please check $ISLogFileDate format."
}
}
else
{
# When $IISLogFileDate not ordered, then get all Files in iis log directory.
$IISLogFullPath = (Get-ChildItem $IISLogPath).FullName
}
$result = foreach ($log in $IISLogFullPath){
[Console]::WriteLine("$log read start.")
# Read $log file
$IISLogFileRaw = Get-Content -Path $log
# Set Header from log file by reading RAW Number 3
$headers = $IISLogFileRaw[3].Replace("#Fields: ","").Replace("-","").Replace("(","").Replace(")","").split(" ")
# Import Log file as Object
$IISLogFileCSV = Import-Csv -Delimiter " " -Header $headers -Path $log
# Remove #* line for date object
$IISLogFileCSV = $IISLogFileCSV | where {$_.date -notlike "#*"}
# Create PSCustomObject
$IISLogFileCSV `
| %{
# Input into variables to prepare making PSCustomObject
$date=$_.date
$time=$_.time
$sip=$_.sip
$csmethod=$_.csmethod
$csuristem=$_.csuristem
$csuriquery=$_.csuriquery
$sport=$_.sport
$csusername=$_.csusername
$cip=$_.cip
$csUserAgent=$_.csUserAgent
$csReferer=$_.csReferer
$scstatus=$_.scstatus
$scsubstatus=$_.scsubstatus
$scwin32status=$_.scwin32status
$timetaken=$_.timetaken
#region Debug check cip resut
<#
[Console]::WriteLine($_.cip)
#>
#endregion
# Check currentIP and previousIP is same or not, then check previous result. If failed, then skip.
# 1. Check PreviousIP and CurrentIP
if(($_.cip -ne $prevCip))
{
try
{
# DNS Name Resolve for IP Address who connected
[System.Net.Dns]::GetHostByAddress($_.cip)
$prevStatus=$true
}
catch
{
# Create Custom Object as blank
$prevStatus=$false
[PSCustomObject]@{
HostName=""
Aliases=""
AddressList=$_.cip
}
}
# flag for next line ip check
$prevCip=$_.cip
}
else
{
# 2. Check previous result was succeed or not
if($prevStatus -eq $false)
{
}
else
{
[System.Net.Dns]::GetHostByAddress($_.cip)
$prevStatus=$true
}
}
#region Debug if result
<#
[Console]::WriteLine(($_.cip -eq $prevCip) -and ($prevStatus -eq $true))
[Console]::WriteLine(($_.cip -eq $prevCip))
[Console]::WriteLine(($prevStatus -eq $true))
#>
#endregion
} `
| %{
# Output as PSCustomObejct and append all file parse data into 1 PSObject
$Output = [PSCustomObject]@{
HostName=$_.HostName
Aliases=[string]$_.Aliases
AddressList=[string]$_.AddressList
date=$date
time=$time
sip=$sip
csmethod=$csmethod
csuristem=$csuristem
csuriquery=$csuriquery
sport=$sport
csusername=$csusername
cip=$cip
csUserAgent=$csUserAgent
csReferer=$csReferer
scstatus=$scstatus
scsubstatus=$scsubstatus
scwin32status=$scwin32status
timetaken=$timetaken
iisFileName=$log
}
# Output currenct PSCustom Object to temp file.
switch ($true){
$ExportAsCsv {$Output | Out-File ./Current_Object_Status_csv.log}
$ExportAsJson {$Output | Out-File ./Current_Object_Status_json.log}
default {$Output | Out-File ./Current_Object_Status.log}
}
# Output to recieve in $result
$Output
}
[Console]::WriteLine("$log read end and go next step..")
}
[Console]::WriteLine("All Log files read done. Starting output...")
}
end
{
switch($true){
$sortUniq {$result | sort AddressList -Unique}
default {$result | sort AddressList}
}
}
}
"Now Running Scripts, please wait...."
switch ($true)
{
$ExportAsCsv
{
if($true -eq $sortUniq)
{
Get-IisLogFileCIps -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -sortUniq -ExportAsCsv | Export-csv ./IIS_c-IP_lists_$((Get-Date).ToString("yyyyMMdd")).csv -NoTypeInformation
}
else
{
Get-IisLogFileCIps -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsCsv | Export-csv ./IIS_c-IP_lists_$((Get-Date).ToString("yyyyMMdd")).csv -NoTypeInformation
}
}
$ExportAsJson
{
if($true -eq $sortUniq)
{
Get-IisLogFileCIps -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -sortUniq -ExportAsJson | ConvertTo-Json -Compress | Out-File ./IIS_c-IP_lists_$((Get-Date).ToString("yyyyMMdd")).json
}
else
{
Get-IisLogFileCIps -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsJson | ConvertTo-Json -Compress | Out-File ./IIS_c-IP_lists_$((Get-Date).ToString("yyyyMMdd")).json
}
}
default { Get-IisLogFileCIps -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" | Export-csv ./IIS_c-IP_lists_$((Get-Date).ToString("yyyyMMdd")).csv -NoTypeInformation}
}
"End Scripts. Please check ./IIS_c-IP_lists.log"
pause
利用例
フォルダ内の全ログを取得、分析する場合はこれで大丈夫です。 (デフォルトでcsv取得)
# バッチで実行の場合
PowerShell .\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\"
# PowerShell.exeで実行
.\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\"
出力をjsonにする場合は以下のように、-ExportAsJsonをつけます。
# バッチで実行の場合
PowerShell .\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsJson
# PowerShell.exeで実行
.\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsJson
更に出力結果をユニーク(一意)なもののみにする場合は、-sortUniq を付けます。
# バッチで実行の場合(csvでuniq)
PowerShell .\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsCsv -sortUniq
# PowerShell.exeで実行の場合(csvでuniq)
.\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsCsv -sortUniq
日付の指定も可能です。調査したい日付がファイル名を、-IISLogFileDate に渡します。
もし何も渡さなければ、IISログフォルダ全てのログを走査します。
datetime型にキャストするので、所謂日付や、Get-Dateで走査した日付をパイプから渡しても大丈夫です。
# バッチで実行の場合(csvでuniq)
PowerShell .\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsCsv -sortUniq -IISLogFileDate "2013/03/07"
# PowerShell.exeで実行の場合(csvでuniq)
.\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsCsv -sortUniq -ExportAsCsv -sortUniq -IISLogFileDate "2013/03/07"
(Get-Date).AddDays("-30") | %{ .\Get-IisLogFileCIps.ps1 -IISLogPath "C:\inetpub\logs\LogFiles\W3SVC1\" -ExportAsCsv -sortUniq -ExportAsCsv -sortUniq -IISLogFileDate "2013/03/07" }
ベースができているので、取得したいパラメーターの調整も簡単に調整できますね。
→ リクエストがあり、IISのログも全て出力するようにしています。
別コマンドレットでもいいですし、パラメーターで渡しても、Module化しても良さそうです。
欲しい人はリクエストをどうぞ。書きますよん。
更新点は、GitHubでどうぞ。