Comando equivalente de cola de Unix en Windows Powershell

Tengo que mirar las últimas líneas de un archivo grande (el tamaño típico es de 500 MB a 2 GB). Estoy buscando un equivalente de tail comandos de Unix para Windows Powershell. Algunas alternativas disponibles en son,

http://tailforwin32.sourceforge.net/

y

  Get-Content [nombre del archivo] |  Select-Object -Last 10 

Para mí, no está permitido usar la primera alternativa, y la segunda alternativa es lenta. ¿Alguien sabe de una implementación eficiente de cola para PowerShell?

Use el parámetro -wait con Get-Content, que muestra las líneas a medida que se agregan al archivo. Esta característica estaba presente en PowerShell v1, pero por alguna razón no está bien documentada en v2.

Aquí hay un ejemplo

 Get-Content -Path "C:\scripts\test.txt" -Wait 

Una vez que haya ejecutado esto, actualice y guarde el archivo y verá los cambios en la consola.

Para ser completo, mencionaré que Powershell 3.0 ahora tiene una bandera -Tail en Get-Content

 Get-Content ./log.log -Tail 10 

obtiene las últimas 10 líneas del archivo

 Get-Content ./log.log -Wait -Tail 10 

obtiene las últimas 10 líneas del archivo y espera más

A partir de la versión 3.0 de PowerShell, el cmdlet Get-Content tiene un parámetro -Tail que debería ser de ayuda. Consulte la ayuda en línea de la biblioteca technet para Get-Content.

Las extensiones de comunidad de PowerShell (PSCX) proporcionan el cmdlet Get-FileTail . Parece una solución adecuada para la tarea. Nota: No lo intenté con archivos extremadamente grandes, pero la descripción dice que intercepta eficazmente los contenidos y está diseñado para archivos de registro grandes.

 NAME Get-FileTail SYNOPSIS PSCX Cmdlet: Tails the contents of a file - optionally waiting on new content. SYNTAX Get-FileTail [-Path]  [-Count ] [-Encoding ] [-LineTerminator ] [-Wait] [] Get-FileTail [-LiteralPath]  [-Count ] [-Encoding ] [-LineTerminator ] [-Wait] [] DESCRIPTION This implentation efficiently tails the cotents of a file by reading lines from the end rather then processing the entire file. This behavior is crucial for ef ficiently tailing large log files and large log files over a network. You can also specify the Wait parameter to have the cmdlet wait and display new content as it is written to the file. Use Ctrl+C to break out of the wait loop. Note that if an encoding is not specified, the cmdlet will attempt to auto-detect the encoding by reading the first character from the file. If no character haven't been written to the file yet, the cmdlet will default to using Unicode encoding . You can override this behavior by explicitly specifying the encoding via the Encoding parameter. 

Utilicé algunas de las respuestas dadas aquí, pero solo un aviso que

 Get-Content -Path Yourfile.log -Tail 30 -Wait 

masticará la memoria después de un tiempo. Un colega dejó tal “cola” el último día y subió a 800 MB. No sé si la cola de Unix se comporta de la misma manera (pero lo dudo). Por lo tanto, está bien usarlo para aplicaciones a corto plazo, pero tenga cuidado con él.

Solo algunas adiciones a respuestas anteriores. Hay alias definidos para Get-Content, por ejemplo, si está acostumbrado a UNIX, puede que le guste cat , y también hay type y gc . Entonces, en lugar de

 Get-Content -Path  -Wait -Tail 10 

puedes escribir

 # Print whole file and wait for appended lines and print them cat  -Wait # Print last 10 lines and wait for appended lines and print them cat  -Tail 10 -Wait 

Tomé la solución de @ hajamie y la envolví en un contenedor de script ligeramente más conveniente.

Agregué una opción para comenzar desde un desplazamiento antes del final del archivo, para que pueda usar la funcionalidad similar a la cola de leer una cierta cantidad desde el final del archivo. Tenga en cuenta que el desplazamiento está en bytes, no en líneas.

También hay una opción para seguir esperando por más contenido.

Ejemplos (suponiendo que guarde esto como TailFile.ps1):

 .\TailFile.ps1 -File .\path\to\myfile.log -InitialOffset 1000000 .\TailFile.ps1 -File .\path\to\myfile.log -InitialOffset 1000000 -Follow:$true .\TailFile.ps1 -File .\path\to\myfile.log -Follow:$true 

Y aquí está el script en sí …

 param ( [Parameter(Mandatory=$true,HelpMessage="Enter the path to a file to tail")][string]$File = "", [Parameter(Mandatory=$true,HelpMessage="Enter the number of bytes from the end of the file")][int]$InitialOffset = 10248, [Parameter(Mandatory=$false,HelpMessage="Continuing monitoring the file for new additions?")][boolean]$Follow = $false ) $ci = get-childitem $File $fullName = $ci.FullName $reader = new-object System.IO.StreamReader(New-Object IO.FileStream($fullName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)) #start at the end of the file $lastMaxOffset = $reader.BaseStream.Length - $InitialOffset while ($true) { #if the file size has not changed, idle if ($reader.BaseStream.Length -ge $lastMaxOffset) { #seek to the last max offset $reader.BaseStream.Seek($lastMaxOffset, [System.IO.SeekOrigin]::Begin) | out-null #read out of the file until the EOF $line = "" while (($line = $reader.ReadLine()) -ne $null) { write-output $line } #update the last max offset $lastMaxOffset = $reader.BaseStream.Position } if($Follow){ Start-Sleep -m 100 } else { break; } } 

Muy básico, pero hace lo que necesita sin módulos adicionales o requisitos de versión PS:

while ($true) {Clear-Host; gc E:\test.txt | select -last 3; sleep 2 }

Con Powershell V2 y versiones posteriores, get-content lee el archivo completo, por lo que no me servía de nada. El siguiente código funciona para lo que necesitaba, aunque es probable que haya algunos problemas con las codificaciones de caracteres. Esto es efectivamente tail -f, pero podría modificarse fácilmente para obtener los últimos x bytes o las últimas x líneas si desea buscar saltos de línea hacia atrás.

 $filename = "\wherever\your\file\is.txt" $reader = new-object System.IO.StreamReader(New-Object IO.FileStream($filename, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)) #start at the end of the file $lastMaxOffset = $reader.BaseStream.Length while ($true) { Start-Sleep -m 100 #if the file size has not changed, idle if ($reader.BaseStream.Length -eq $lastMaxOffset) { continue; } #seek to the last max offset $reader.BaseStream.Seek($lastMaxOffset, [System.IO.SeekOrigin]::Begin) | out-null #read out of the file until the EOF $line = "" while (($line = $reader.ReadLine()) -ne $null) { write-output $line } #update the last max offset $lastMaxOffset = $reader.BaseStream.Position } 

Encontré la mayor parte del código para hacer esto aquí .

prueba las Windows Server 2003 Resource Kit Tools

contiene un tail.exe que se puede ejecutar en el sistema de Windows.

https://www.microsoft.com/en-us/download/details.aspx?id=17657