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 500MB-2GB). Estoy buscando un equivalente de Unix command tail para Windows Powershell. Algunas alternativas disponibles en son,

Http://tailforwin32.sourceforge.net /

Y

Get-Content [filename] | 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 tail para PowerShell?

Author: Gabe, 2010-12-13

10 answers

Utilice 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 se documentó bien en v2.

Aquí hay un ejemplo

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

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

 377
Author: ravikanth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-05 15:05:55

Para completar, mencionaré que Powershell 3.0 ahora tiene una bandera de cola 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

 119
Author: George Mauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-13 20:48:18

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

 110
Author: Dan Blanchard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-31 12:33:46

PowerShell Community Extensions (PSCX) proporciona el Get-FileTail cmdlet . Parece una solución adecuada para la tarea. Nota: No lo probé con archivos extremadamente grandes, pero la descripción dice que sigue eficientemente el contenido 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] <String[]> [-Count <Int32>] [-Encoding <EncodingParameter>] [-LineTerminator <String>] [-Wait] [<CommonParameters>]

    Get-FileTail [-LiteralPath] <String[]> [-Count <Int32>] [-Encoding <EncodingParameter>] [-LineTerminator <String>] [-Wait] [<CommonParameters>]

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.
 17
Author: Roman Kuzmin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 14:42:41

He utilizado algunas de las respuestas dadas aquí, pero solo un heads up que

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

Masticará la memoria después de un tiempo. Un colega dejó tal" cola " en el último día y subió a 800 MB. No se si Unix tail 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.

 15
Author: John Lockwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-23 15:08:34

Solo algunas adiciones a las respuestas anteriores. Hay alias definidos para Get-Content, por ejemplo si estás acostumbrado a UNIX te puede gustar cat, y también hay type y gc. Así que en lugar de

Get-Content -Path <Path> -Wait -Tail 10

Puedes escribir

# Print whole file and wait for appended lines and print them
cat <Path> -Wait
# Print last 10 lines and wait for appended lines and print them
cat <Path> -Tail 10 -Wait
 13
Author: Mikael Sundberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-08 08:08:34

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

He añadido una opción para comenzar desde un desplazamiento antes del final del archivo, por lo que puede utilizar la funcionalidad de cola-como de leer una cierta cantidad desde el final del archivo. Nota el desplazamiento en bytes, no líneas.

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

Ejemplos (suponiendo que guardes 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 sí mismo...

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;
    }
}
 3
Author: Brian Reischl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-11 16:10:23

Usando Powershell V2 y versiones anteriores, get-content lee todo el archivo, por lo que no me sirvió de nada. El siguiente código funciona para lo que necesitaba, aunque es probable que haya algunos problemas con la codificación 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í.

 2
Author: hajamie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-17 16:05:34

Muy básico, pero hace lo que necesita sin ningún módulo adicional o requisitos de versión de PS:

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

 1
Author: Jesse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-24 03:10:52

Intenta Windows Server 2003 Resource Kit Tools

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

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

 0
Author: starshine wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-22 09:14:43