Truncar un archivo de registro por fecha y hora con Powershell 2.0

0

Tenemos un archivo de registro simple. Se vuelve demasiado grande o las entradas son irrelevantes a medida que envejecen. Las entradas tienen un prefijo de fecha y hora similar a este:

22/01/15 01:54:17 -I- Comenzar a procesar cosas

Ocasionalmente, las entradas de registro abarcan varias líneas como esta:

01/23/15 01:18:00 -E- java.io.IOException: (101) Error between keyboard and chair
     at this.mod.no.worky(what_were_you_thinking:duh)

Simplemente queremos eliminar las entradas (enteras) antes de una fecha límite, por ejemplo, llamarlo 30 días.

Las soluciones que se truncan a un número fijo de líneas o bytes no funcionan en este caso.

Intento más reciente con un rendimiento terrible:

$cutDatePtrn = "^" + (get-date).AddDays(-30).tostring("MM/dd/yy ")
$newStartLine = (select-string -Path $logFile -Pattern $cutDatePtrn -Quiet -List).LineNumber
$tmp = $logFile + '.tmp'
get-content $logFile | select -skip $newStartLine | out-file $tmp
Vic
fuente
Correcto. He estado perdiendo el tiempo con StreamReader / StreamWriter ... En general, gira en torno a encontrar la primera línea que comienza después de la fecha de corte y escribir el resto del archivo.
Vic
puede intentar basar su solución en esta respuesta: stackoverflow.com/a/4192419/1123692
wmz
Gracias @wmz. Pero la publicación a la que hace referencia aboga por no usar PowerShell para esto (estoy de acuerdo) y usar StreamReader si uno insiste en usar Powershell. Mi proyecto está buscando específicamente una implementación de Powershell que sea más rápida que la disponible usando streamreader / streamwriter.
Vic
No estoy seguro si te entendí [que solo quieres usar cmdlets], pero la pregunta que vinculé incluye algunos consejos sobre cómo acelerar el contenido (es decir, no lo asignes a variable y utilices alto -ReadCount), pero si Sería yo quien engañaría y usaría Logparserpara la tarea ( technet.microsoft.com/en-us/scriptcenter/dd919274.aspx , que técnicamente podría llamarse 'implementación de powershell' ya que expone la interfaz com para que pueda consultar desde PS con new-object -com)
wmz

Respuestas:

2

Aquí está la solución PowerShell usando Streams. Tarda ~ 60 segundos en procesar un archivo de 1GB en mi computadora portátil ( i3 2.5GHz, 4GB RAM, HDD 5400RPM) . Sin embargo, sigue siendo tres veces más lento que LogParser :

LOGPARSER "Select Text from C:\Path\To\log.file where Text like '01/22/15%'" -i:TEXTLINE -q:Off
$LogFolder = 'c:\Path\To\Log\Folder'
$Filter = '*.log'
$Postfix = '.tmp'
$cutDatePtrn = '^' + (Get-Date).AddDays(-30).ToString('MM/dd/yy')

# Iterate over each log file in the $LogFolder
Get-ChildItem -LiteralPath $LogFolder -Filter $Filter |
    ForEach-Object {
        Write-Host "Current file: $($_.FullName)"
        $InFile = New-Object -TypeName System.IO.StreamReader -ArgumentList $_.FullName

        Write-Host 'Processing file...'

        $WriteFile = $false
        while(($line = $InFile.ReadLine()) -ne $null)
        {
            if((-not $WriteFile) -and ($line -notmatch $cutDatePtrn))
            {
                continue
            }
            elseif((-not $WriteFile) -and ($line -match $cutDatePtrn))
            {
                Write-Host 'Found match:'
                Write-Host $line

                $WriteFile = $true
                $TmpFile = $_.FullName + $Postfix

                Write-Host "Creating new temporary file: $TmpFile"
                $OutFile = New-Object -TypeName System.IO.StreamWriter -ArgumentList $TmpFile, $false
            }

            $OutFile.WriteLine($line)
        }

        Write-Host 'Done processing, cleaning up...'
        if($OutFile)
        {

            $OutFile.Flush()
            $OutFile.Close()
            $OutFile.Dispose()
        }

        $InFile.Close()
        $InFile.Dispose()

        if(Test-Path $TmpFile -PathType Leaf)
        {
            Write-Host "Deleting original file: $($_.FullName)"
            Remove-Item -Path $_.FullName -Force

            Write-Host "Renaming temporary file: $TmpFile -> $($_.FullName)"
            Rename-Item -Path $TmpFile -NewName $_.FullName -Force
        }

        Write-Host "Finished processing file: $($_.FullName)"
        }
beatcracker
fuente
Ah, buen esfuerzo. Déjame ver esto y publicar una actualización. Gracias beatcracker.
Vic