Powershell解析filezilla日志

时间:2014-04-22 17:45:46

标签: powershell filezilla

我需要从filezilla日志中提取日期,时间和文件名,以便将其插入数据库。

这是我到目前为止所做的:

Select-String "C:\Scripts\testing\SSIS\testfiles\fzs-2014-04-15.log" -Pattern "STOR" -AllMatches
Foreach($line in $lines){
$line = $line -replace "C:\Path-to-logs\filezilla.log.*\) ",""
    $line = $line -replace "[AM|PM].* STOR ",""
    $line -split " "
}

我得到以下结果:

C:\path-to-logs\filezilla.log:114:(003173) 4/15/2014 3:04:20 AM - cwwsfge (192.168.250)> STOR NewFileupload.TXT
C:\path-to-logs\filezilla.log.log:210:(000182) 4/15/2014 6:21:21 AM - refect(192.168.250)> STOR Testfile_20140415
C:\path-to-logs\filezilla.log.log:662:(000179) 4/15/2014 6:27:13 AM - refect (192.168.2)> STOR FreeMoney.txt

那么,如果我在foreach中获得该信息,该怎么办?

谢谢!

3 个答案:

答案 0 :(得分:1)

编辑以匹配上述更改。我认为你仍然可以使用一个正则表达式-split,然后挑选你需要的元素。试试这个:

Foreach($line in $lines){
$parts = $line  -split '\) | - |\> STOR |:\('
    $logdate = [DateTime]::Parse($parts[2])
    $filename = $parts[4]

    write-host "Filename: $filename"
    write-host "Filedate: $($logdate.Date.ToShortDateString())"
    write-host "Filetime: $($logdate.TimeOfDay)`n"
}

基本上这是匹配“)”,“ - ”,“> STOR”或“:(”并将这些线分开。如果格式一致,每次传递中应该有5个元素。我添加了一些用于选择文件名并解析日期的代码,它会为上面示例中的值生成此值:

Filename: NewFileupload.TXT
Filedate: 4/15/2014
Filetime: 03:04:20

Filename: Testfile_20140415
Filedate: 4/15/2014
Filetime: 06:21:21

Filename: FreeMoney.txt
Filedate: 4/15/2014
Filetime: 06:27:13

答案 1 :(得分:0)

使用前面的答案,我构建了一个脚本,以制表符分隔的格式输出。

$logpath = "C:\Program Files (x86)\FileZilla Server\Logs"

# combine all the logs into one file
gci "$logpath\*.log" | sort LastWriteTime | % {$(Get-Content $_)} | Set-Content "$logpath\combo.txt"

# scan lines only containing login,file upload, and download
$lines = Select-String "$logpath\combo.txt" -Pattern "> RETR|> STOR|230 Logged on" -AllMatches

Foreach($line in $lines){
    $parts = $line  -split '\) | - |\> |:\('
    $logdate = [DateTime]::Parse($parts[2])
    $filename = $parts[4].Replace("230 Logged","Logged")
    $user = $parts[3]

    $user,$filename,$logdate -join "`t" | Out-File -FilePath "$logpath\output.txt" -Append -Width 500
}

答案 2 :(得分:0)

我创建了一个脚本来将日志解析为一种表单,该表单更易于使用/在这里与其他对OP有类似要求的人共享。

对于特定问题,下面是如何使用此代码:

[string[]]$logs = @('C:\Scripts\testing\SSIS\testfiles\fzs-2014-04-15.log') # you could add more / get these via Get-ChildItem / etc
[PSCustomObject[]]$data =  $logs | 
    Get-FzLogData | 
    ForEach-Object {
        if($_.Msg -match '\s*STOR\s(?<Filename>.+)') {
            [PSCustomObject]@{
                FileName = $Matches['FileName']
                DateTime = $_.DateTime
            }
        }
    }
$data # just shows the data for now...

完整代码:

class FzLogEntry {
    [long]$SessionId
    [DateTime]$DateTime
    [string]$User
    [version]$ClientIp # I've used version assuming it's always IPv4... if that assumption's wrong we may have to amend to string
    [string]$Msg
    FzLogEntry(){}
}

Function Get-FzLogData {
    [OutputType('FzLogEntry[]')]
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string[]]$Path
    )
    Process {
        foreach ($p in $Path) {
            Get-Content -Path $p | ConvertTo-FzLogEntry
        }
    }
}
Function ConvertTo-FzLogEntry {
    [OutputType('FzLogEntry')]
    [CmdletBinding(DefaultParameterSetName = 'Default')]
    Param (
        [Parameter(ParameterSetName = 'Default', Mandatory = $true, ValueFromPipeline = $true)]
        [Parameter(ParameterSetName = 'Unparsable', Mandatory = $true, ValueFromPipeline = $true)]
        [string[]]$Line
        ,
        [Parameter(ParameterSetName = 'Unparsable', Mandatory = $true)]  # I don't really have a need for this; but it may be helpful if debugging to know when lines are not processed / have a gap in your results...
        [Switch]$IncludDefaultForUnparsable
        ,
        [Parameter(ParameterSetName = 'Unparsable')]
        [FzLogEntry]$DefaultValue = $null
    )
    Begin {
        [string]$regexPattern = @'
^\(
(?<SessionId>\d+)
\)\s
(?<DateTime>\S+\s\S+)
\s\-\s
(?<User>(?:\([^\)]+\))|(?:\S+))
\s\(
(?<ClientIp>[^>]+)
\)>\s*
(?<Msg>.*)
$
'@ -replace '[\r\n]+', ''    
    }
    Process {
        foreach ($l in $Line) {
            if ($l -match $regexPattern) {
                $fiddle = $Matches
                $fiddle.Remove(0)
                $fiddle.DateTime = $fiddle.DateTime -replace '^(\d+)\/(\d+)\/(\d+)', '$3-$2-$1' #correct date format to something that PS can auto convert to a DateTime.  Assumes dd/mm/yyyy format in the logs
                [FzLogEntry]$fiddle
            } else {
                if ($IncludDefaultForUnparsable.IsPresent) {
                    $DefaultValue
                }
            }
        }
    }
}

如果我对此功能进行任何更改,相关的Gist将保持最新。