คำสั่ง Unix tail เทียบเท่าใน Windows Powershell


350

ฉันต้องดูสองสามบรรทัดสุดท้ายของไฟล์ขนาดใหญ่ (ขนาดปกติคือ 500MB-2GB) ฉันกำลังมองหาคำสั่ง Unix ที่เทียบเท่าtailกับ Windows Powershell มีทางเลือกสองทางให้เลือกคือ

http://tailforwin32.sourceforge.net/

และ

รับเนื้อหา [ชื่อไฟล์] | เลือกวัตถุ -Last 10

สำหรับฉันมันไม่ได้รับอนุญาตให้ใช้ตัวเลือกแรกและตัวเลือกที่สองช้า ไม่มีใครรู้ว่าการใช้หางอย่างมีประสิทธิภาพสำหรับ PowerShell


2
เราจะรู้ได้อย่างไรว่าคุณจะได้รับอนุญาตให้ใช้สิ่งที่เราแนะนำถ้าคุณไม่บอกว่าทำไมคุณไม่ได้รับอนุญาตให้ใช้ทางเลือกแรก?
Gabe

3
มีเหตุผลใดที่คุณไม่สามารถใช้tailคำสั่งที่ให้ไว้ในsourceforge.net/projects/unxutils/files/unxutils/current/… ?
Gabe

1
นี่คือในเครื่องผลิตที่ฉันไม่ได้รับอนุญาตให้คัดลอกสำเนาไฟล์ปฏิบัติการภายนอกใด ๆ นโยบายแปลก ๆ :) ช่วยไม่ได้ ขอบคุณสำหรับลิงก์ Unxutils
mutelogan

https://devcentral.f5.com/blogs/us/unix-to-powershell-tailแสดงการใช้งาน PoSH บริสุทธิ์ของสิ่งนี้
Yevgeniy

ไม่จำเป็นต้องใช้ Select-Object: Get-Content [filename] -last 10และเพิ่ม-tail-f
MortenB

คำตอบ:


492

ใช้-waitพารามิเตอร์กับ Get-Content ซึ่งแสดงบรรทัดขณะที่เพิ่มลงในไฟล์ คุณลักษณะนี้มีอยู่ใน PowerShell v1 แต่ด้วยเหตุผลบางอย่างที่ไม่ได้บันทึกไว้อย่างดีใน v2

นี่คือตัวอย่าง

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

เมื่อคุณเรียกใช้งานแล้วให้อัปเดตและบันทึกไฟล์และคุณจะเห็นการเปลี่ยนแปลงในคอนโซล


16
น่าสนใจ ฉันจะคิดว่าการขัดแย้งทั้งหมดที่มีอยู่ก็ปรากฏขึ้นในความช่วยเหลือ แต่man gc -par waitบอกฉันว่าไม่มีพารามิเตอร์ แต่ฉันคิดว่าสิ่งนี้ไม่ได้แก้ปัญหาที่ OP มีเนื่องจากพวกเขาถามtailไม่ใช่tail -fและมีการใช้งานที่มีประสิทธิภาพเช่นกัน เนื่องจากไฟล์นี้อ่านไฟล์ฉบับสมบูรณ์ก่อนส่งคืนบรรทัดสุดท้ายนี่จึงเป็นเรื่องเจ็บปวดสำหรับขนาดไฟล์ที่พวกเขาคาดหวัง
Joey

5
FYI นี่คือสิ่งที่การดำเนินการของ Get-FileTail (alias tail) ใน PSCX หากคุณสงสัยคุณสามารถดูซอร์สโค้ด: pscx.codeplex.com/SourceControl/changeset/view/78514#1358075
Keith Hill

7
@Joey -Wait เป็นพารามิเตอร์แบบไดนามิกที่ใช้กับผู้ให้บริการ FileSystem เท่านั้น GC สามารถใช้กับผู้ให้บริการที่ใช้ API นั้นได้ วิธีเดียวที่นอกเหนือจากเอกสารที่ฉันรู้ว่าจะค้นพบสิ่งเหล่านี้คือการใช้ (gcm Get-Content) พารามิเตอร์จากภายในเส้นทางของผู้ให้บริการที่เหมาะสม อย่าใช้นามแฝง "gc" เนื่องจากพารามิเตอร์แบบไดนามิกจะไม่แสดงขึ้นมา
JasonMArcher

11
ฉันรู้ว่าเมื่อไม่นานมานี้ แต่สิ่งนี้ต้องการให้กระบวนการเขียนลงไฟล์เพื่อเปิดผนวกต่อปิดก่อนที่ Get-Content จะทำงาน หากขั้นตอนการเขียนไม่เคยปิดไฟล์มันจะไม่ทำงานซึ่งไม่ใช่กรณีของ tail -f
David Newcomb

15
ผิดปกติ - รอเพียงแสดงบรรทัดใหม่ให้ฉันเมื่อฉันเข้าถึงไฟล์บันทึกในบางวิธี (เช่นเลือกใน Windows Explorer) Tail ให้การปรับปรุงเนื่องจากมีการเขียนบรรทัดใหม่ลงในไฟล์ของฉัน ด้วย -Wait ฉันสามารถเปิดหน้าต่าง PowerShell ได้อย่างมีความสุขโดยไม่แสดงบรรทัดใหม่ในขณะที่กำลังเขียนไฟล์ หากฉันปรากฏขึ้นมาแล้วคลิกที่ไฟล์ใน Windows Explorer ทันใดนั้น PowerShell "ตื่นขึ้น" และจับสายที่เหลืออยู่ นี่เป็นข้อบกพร่องหรือไม่?
JoshL

199

เพื่อความสมบูรณ์ฉันจะพูดถึงว่า Powershell 3.0 ในขณะนี้มีการตั้งค่าสถานะ -Tail บน Get-Content

Get-Content ./log.log -Tail 10

รับ 10 บรรทัดสุดท้ายของไฟล์

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

รับ 10 บรรทัดสุดท้ายของไฟล์และรอมากกว่านี้

นอกจากนี้สำหรับผู้ใช้ * ระวังโปรดทราบว่าระบบส่วนใหญ่ใช้catเป็น Get-Content ดังนั้นจึงมักใช้งานได้

cat ./log.log -Tail 10

@LauraLiparulo สิ่งนี้ไม่ทำงาน? ฉันใช้มันมาก่อนแน่นอน
George Mauer

4
ฉันเพิ่งใช้มันและมันได้ผลในรูปแบบนี้Get-Content .\test.txt -Wait -Tail 1
Coops

@LauraLiparulo - ทำงานให้ฉันด้วย:Get-Content -Path .\sync.log -Wait -Tail 10
elika kohen

ใน ISE ฉันเคยใช้ในขณะที่ ($ true) / sleep และเปลี่ยนไปใช้อันนี้ แต่อันนี้ล็อค ISE ทั้งหมดและไม่สามารถเรียกใช้สคริปต์บนแท็บอื่น ๆ ฉันควรเริ่มต้นอินสแตนซ์ ISE ใหม่หรือไม่
Teoman shipahi

@Tomomhiphipahi -Waitพารามิเตอร์ไม่ได้ผลสำหรับคุณใช่ไหม?
George Mauer

116

ในฐานะของ PowerShell เวอร์ชัน 3.0 cmdlet Get-Content มีพารามิเตอร์-Tailที่ควรช่วย ดูวิธีใช้ออนไลน์ของห้องสมุดเทคนิคสำหรับรับเนื้อหา


1
เชื่อมโยงไปยังดาวน์โหลดได้ที่นี่ - microsoft.com/en-us/download/details.aspx?id=34595
Gedrox

4
หมายเหตุสำหรับบางคน - PS 3.0 ไม่สามารถใช้งานได้กับ Windows XP และ Vista
tjmoore

1
ฉันใช้เทคนิคที่กล่าวถึงโดย Dan แต่ฉันบันทึกไว้ในโปรไฟล์ $ เปิดด้วย notepad $ PROFILE จากนั้นในเอกสารข้อความสร้างฟังก์ชั่นใหม่: ฟังก์ชั่น Tail ($ path) {Get-content -tail 15 -path $ path -wait} วิธีนี้คุณสามารถเข้าถึงฟังก์ชั่นได้ทุกครั้งที่คุณเริ่ม PowerShell
Jake Nelson

นี่ควรเป็นคำตอบที่ยอมรับได้ - การรอธงที่กล่าวถึงในคำตอบที่ยอมรับในปัจจุบันใช้ไม่ได้อีกต่อไป
Abdullah Leghari

21

ฉันใช้คำตอบบางข้อที่ให้ไว้ที่นี่

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

จะเคี้ยวหน่วยความจำหลังจากชั่วครู่ เพื่อนร่วมงานคนหนึ่งออกจาก "หาง" ขึ้นไปในวันสุดท้ายและมันก็สูงถึง 800 MB ฉันไม่รู้ว่าหาง Unix ทำงานในลักษณะเดียวกัน (แต่ฉันสงสัย) ดังนั้นจึงเป็นเรื่องดีที่จะใช้สำหรับแอปพลิเคชันระยะสั้น แต่ระวังด้วย


18

PowerShell ชุมชน Extensions (PSCX)ให้cmdletGet-FileTail ดูเหมือนโซลูชันที่เหมาะสมสำหรับงาน หมายเหตุ: ฉันไม่ได้ลองกับไฟล์ที่มีขนาดใหญ่มาก แต่คำอธิบายบอกว่ามันมีประสิทธิภาพในการจัดการเนื้อหาและมันถูกออกแบบมาสำหรับไฟล์บันทึกขนาดใหญ่

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.

1
มีข้อบกพร่องในรุ่นปัจจุบันที่ได้รับการแก้ไขในบิตรายวัน ฉันขอแนะนำให้จับบิตล่าสุดและรวบรวมอย่างน้อยก็จนกว่าเราจะได้รับการอัพเดทเวอร์ชั่น
Keith Hill

7
เวอร์ชั่น 2.0 ใช้เวลานานในการแสดง 10 บรรทัดสุดท้ายของไฟล์ 1GB csv และแตกต่างจากGet-Content [filename] | Select-Object -Last 10ไฟล์ที่ไม่สามารถยกเลิกได้
Jader Dias

15

เพียงแค่เพิ่มเติมบางส่วนของคำตอบก่อนหน้า มีนามแฝงกำหนดไว้สำหรับรับเนื้อหาตัวอย่างเช่นถ้าคุณจะใช้ในการ UNIX คุณอาจชอบcatนอกจากนี้ยังมีและและtype gcดังนั้นแทนที่จะ

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

คุณสามารถเขียน

# 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

3

การใช้ Powershell V2 และด้านล่าง get-content จะอ่านไฟล์ทั้งหมดดังนั้นมันจึงไม่มีประโยชน์กับฉัน รหัสต่อไปนี้ใช้งานได้ในสิ่งที่ฉันต้องการแม้ว่าจะมีปัญหาบางอย่างเกี่ยวกับการเข้ารหัสอักขระ นี่คือ tail-f อย่างมีประสิทธิภาพ แต่สามารถแก้ไขได้อย่างง่ายดายเพื่อรับ x ไบต์สุดท้ายหรือบรรทัด x สุดท้ายหากคุณต้องการค้นหาย้อนหลังเพื่อหาตัวแบ่งบรรทัด

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

ผมพบว่าส่วนใหญ่ของรหัสที่จะทำเช่นนี้ได้ที่นี่


1
เป็นความจริงไหมที่ Get-Content พร้อมตัวเลือก -Tail จะอ่านไฟล์ทั้งหมด? สำหรับไฟล์ขนาดใหญ่มันดูเหมือนว่าใช้ได้สำหรับฉัน
Govert

ฉันเชื่อว่ามันขึ้นอยู่กับรุ่น PS ฉันได้อัพเดตคำตอบแล้ว ฉันติดอยู่บนเซิร์ฟเวอร์ที่ไม่มีความสามารถในการติดตั้งอะไรในเวลานั้นดังนั้นโค้ดด้านบนจึงมีประโยชน์
hajamie

3

ฉันใช้วิธีแก้ปัญหาของ @hajamie และห่อมันลงในกระดาษห่อหุ้มสคริปต์ที่สะดวกกว่าเล็กน้อย

ฉันได้เพิ่มตัวเลือกให้เริ่มจากอ็อฟเซ็ตก่อนสิ้นสุดไฟล์ดังนั้นคุณสามารถใช้ฟังก์ชั่นคล้ายหางของการอ่านจำนวนหนึ่งจากส่วนท้ายของไฟล์ หมายเหตุออฟเซ็ตเป็นไบต์ไม่ใช่บรรทัด

นอกจากนี้ยังมีตัวเลือกให้รอเนื้อหาเพิ่มเติมต่อไป

ตัวอย่าง (สมมติว่าคุณบันทึกเป็น 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

และนี่คือสคริปต์ของตัวเอง ...

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


0

ขั้นพื้นฐานมาก แต่ทำในสิ่งที่คุณต้องการโดยไม่มีโมดูลเสริมหรือข้อกำหนดรุ่น PS:

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


4
นั่นโหดร้ายกับไฟล์ขนาดใหญ่
Pecos Bill

วิธีแก้ปัญหาของฉันคือ: while($true) { Clear-Host; Get-Content <filename> -tail 40; sleep 1 }:)
NoLifeKing


0

มีการตอบที่ถูกต้องมาก แต่ไม่มีของพวกเขามีเหมือนกันไวยากรณ์เป็นหางในลินุกซ์ ฟังก์ชั่นดังต่อไปนี้สามารถเก็บไว้ในของคุณ$Home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1สำหรับความยั่งยืน (ดูเอกสารโปรไฟล์ PowerShellสำหรับรายละเอียดเพิ่มเติม)

สิ่งนี้ช่วยให้คุณโทร ...

tail server.log
tail -n 5 server.log
tail -f server.log
tail -Follow -Lines 5 -Path server.log

ซึ่งค่อนข้างใกล้เคียงกับไวยากรณ์ของ linux

function tail {
<#
    .SYNOPSIS
        Get the last n lines of a text file.
    .PARAMETER Follow
        output appended data as the file grows
    .PARAMETER Lines
        output the last N lines (default: 10)
    .PARAMETER Path
        path to the text file
    .INPUTS
        System.Int
        IO.FileInfo
    .OUTPUTS
        System.String
    .EXAMPLE
        PS> tail c:\server.log
    .EXAMPLE
        PS> tail -f -n 20 c:\server.log
#>
    [CmdletBinding()]
    [OutputType('System.String')]
    Param(
        [Alias("f")]
        [parameter(Mandatory=$false)]
        [switch]$Follow,

        [Alias("n")]
        [parameter(Mandatory=$false)]
        [Int]$Lines = 10,

        [parameter(Mandatory=$true, Position=5)]
        [ValidateNotNullOrEmpty()]
        [IO.FileInfo]$Path
    )
    if ($Follow)
    {
        Get-Content -Path $Path -Tail $Lines -Wait
    }
    else
    {
        Get-Content -Path $Path -Tail $Lines
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.