web-dev-qa-db-fra.com

Commande équivalente à la queue Unix dans Windows Powershell

Je dois regarder les dernières lignes d'un fichier volumineux (taille typique: 500 Mo - 2 Go). Je recherche un équivalent de la commande Unix tail pour Windows Powershell. Quelques alternatives disponibles sur sont,

http://tailforwin32.sourceforge.net/

et

Get-Content [nom du fichier] | Select-Object -Last 10

Pour moi, il n'est pas permis d'utiliser la première alternative et la seconde alternative est lente. Est-ce que quelqu'un connaît une implémentation efficace de tail pour PowerShell?.

320
mutelogan

Utilisez le paramètre -wait avec Get-Content, qui affiche les lignes au fur et à mesure qu'elles sont ajoutées au fichier. Cette fonctionnalité était présente dans PowerShell v1, mais pour une raison quelconque n’est pas bien documentée dans la v2.

Voici un exemple

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

Une fois que vous avez lancé ceci, mettez à jour et enregistrez le fichier et vous verrez les modifications sur la console.

448
ravikanth

Pour être complet, je mentionnerai que Powershell 3.0 a maintenant un drapeau -Tail sur Get-Content

Get-Content ./log.log -Tail 10

récupère les 10 dernières lignes du fichier

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

obtient les 10 dernières lignes du fichier et attend plus

En outre, pour les utilisateurs * nix, notez que la plupart des systèmes alias cat to Get-Content, donc cela fonctionne généralement

cat ./log.log -Tail 10
166
George Mauer

Depuis la version 3.0 de PowerShell, la cmdlet Get-Content comporte un paramètre - Tail qui devrait vous aider. Voir l'aide en ligne de la bibliothèque technet pour Get-Content.

114
Dan Blanchard

J'ai utilisé certaines des réponses données ici, mais juste un avertissement qui

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

va mâcher la mémoire après un certain temps. Un collègue a laissé une telle "queue" au cours de la dernière journée pour atteindre 800 Mo. Je ne sais pas si Unix tail se comporte de la même manière (mais j'en doute). Donc, c'est bien d'utiliser pour des applications à court terme, mais soyez prudent avec cela.

21
John Lockwood

Les extensions de communauté PowerShell (PSCX) fournit la Get-FileTail cmdlet . Cela semble être une solution adaptée à la tâche. Remarque: je ne l'ai pas essayé avec des fichiers extrêmement volumineux, mais la description indique que le contenu en est réduit au minimum et qu'il est conçu pour les fichiers journaux volumineux.

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.
18
Roman Kuzmin

Juste quelques ajouts aux réponses précédentes. Il existe des alias définis pour Get-Content. Par exemple, si vous êtes habitué à UNIX, vous pourriez aimer cat, et il y a aussi type et gc. Donc au lieu de

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

tu peux écrire

# 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
15
Mikael Sundberg

À l'aide de Powershell version 2 et antérieure, get-content lit l'intégralité du fichier, ce qui ne m'a donc servi à rien. Le code suivant fonctionne pour ce dont j'avais besoin, bien qu'il y ait probablement des problèmes avec les encodages de caractères. C'est effectivement tail -f, mais il pourrait être facilement modifié pour obtenir les x derniers octets, ou les dernières x lignes si vous souhaitez rechercher des sauts de ligne en arrière.

$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
}

J'ai trouvé la plupart du code pour faire ceci ici .

3
hajamie

J'ai pris la solution de @ hajamie et l'ai emballée dans un wrapper de script légèrement plus pratique.

J'ai ajouté une option permettant de démarrer à partir d'un décalage avant la fin du fichier. Vous pouvez donc utiliser la fonctionnalité similaire à la lecture d'une certaine quantité à partir de la fin du fichier. Notez que le décalage est en octets et non en lignes.

Il existe également une option pour continuer à attendre pour plus de contenu.

Exemples (en supposant que vous enregistrez ceci sous 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

Et voici le script lui-même ...

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
Brian Reischl

essayez Windows Server 2003 Resource Kit Tools

il contient un tail.exe qui peut être exécuté sur le système Windows.

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

2
starshine wang

Très basique, mais fait ce dont vous avez besoin sans modules additionnels ni exigences de version PS:

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

1
Jesse

Probablement trop tard pour une réponse mais essayez celui-ci

Get-Content <filename> -tail <number of items wanted>
0
EvosDeMercile