Unix tail ekivalen dengan perintah di Windows Powershell

349

Saya harus melihat beberapa baris terakhir dari file besar (ukuran khasnya adalah 500MB-2GB). Saya mencari yang setara dengan perintah Unix tailuntuk Windows Powershell. Beberapa alternatif yang tersedia adalah,

http://tailforwin32.sourceforge.net/

dan

Dapatkan-Konten [nama file] | Select-Object -Last 10

Bagi saya, tidak diperbolehkan menggunakan alternatif pertama, dan alternatif kedua lambat. Adakah yang tahu tentang implementasi ekor yang efisien untuk PowerShell.

mutelogan
sumber
2
Bagaimana kami bisa tahu jika Anda akan diizinkan untuk menggunakan apa yang kami sarankan jika Anda tidak mengatakan mengapa Anda tidak diizinkan untuk menggunakan alternatif pertama?
Gabe
3
Apa alasan Anda tidak dapat menggunakan tailperintah yang disediakan di sourceforge.net/projects/unxutils/files/unxutils/current/… ?
Gabe
1
ini di mesin produksi di mana saya tidak diizinkan untuk menyalin semua file eksternal yang dapat dieksekusi. Beberapa kebijakan aneh. :) Tidak bisa menahannya. Terima kasih atas tautan Unxutils.
mutelogan
https://devcentral.f5.com/blogs/us/unix-to-powershell-tail menunjukkan implementasi PoSH murni ini.
Yevgeniy
Tidak perlu menggunakan Select-Object: Get-Content [filename] -last 10dan tambahkan -tailuntuk -f
MortenB

Jawaban:

492

Gunakan -waitparameter dengan Get-Content, yang menampilkan baris ketika mereka ditambahkan ke file. Fitur ini hadir di PowerShell v1, tetapi untuk beberapa alasan tidak didokumentasikan dengan baik di v2.

Berikut ini sebuah contoh

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

Setelah Anda menjalankan ini, perbarui dan simpan file dan Anda akan melihat perubahan di konsol.

ravikanth
sumber
16
Menarik. Saya akan berpikir bahwa semua argumen yang ada juga muncul dalam bantuan, namun man gc -par waitmemberi tahu saya tidak ada parameter. Tapi saya pikir ini tidak menyelesaikan masalah yang dimiliki OP, karena mereka meminta tail, tidak tail -fdan implementasi yang efisien juga. Karena yang ini juga membaca file lengkap sebelum mengembalikan baris terakhir, ini menyakitkan untuk ukuran file yang mereka harapkan.
Joey
5
FYI, inilah yang dilakukan oleh implementasi Get-FileTail (alias tail) di PSCX. Jika Anda penasaran, Anda dapat melihat kode sumber: pscx.codeplex.com/SourceControl/changeset/view/78514#1358075
Keith Hill
7
@ Joey -Tunggu adalah parameter dinamis yang hanya berlaku untuk penyedia FileSystem. GC dapat digunakan pada penyedia apa pun yang mengimplementasikan API itu. Satu-satunya cara selain dokumentasi yang saya tahu menemukan ini adalah dengan menggunakan (gcm Get-Content). Parameter dari dalam jalur penyedia yang sesuai. Jangan gunakan alias "gc" karena parameter dinamis tidak akan muncul.
JasonMArcher
11
Saya tahu itu beberapa waktu yang lalu, tetapi ini membutuhkan proses penulisan ke file untuk membuka, menambahkan, menutupnya sebelum Get-Content akan berfungsi. Jika proses penulisan tidak pernah menutup file maka itu tidak akan berfungsi yang tidak terjadi dengan tail -f.
David Newcomb
15
Anehnya, -Tunggu hanya menunjukkan saya baris baru ketika saya mengakses file log dalam beberapa cara (seperti memilihnya di Windows Explorer). Tail menyediakan pembaruan saat baris baru ditulis ke file saya. Dengan -Tunggu, saya dapat membiarkan jendela PowerShell terbuka dengan gembira tanpa menunjukkan baris baru saat file sedang ditulis. Jika saya kemudian muncul dan mengklik file di Windows Explorer, tiba-tiba PowerShell "bangun" dan mengejar baris yang tersisa. Apakah ini bug?
JoshL
198

Untuk kelengkapan saya akan menyebutkan bahwa Powershell 3.0 sekarang memiliki flag -Tail pada Get-Content

Get-Content ./log.log -Tail 10

mendapat 10 baris terakhir file

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

mendapat 10 baris terakhir file dan menunggu lebih

Juga, untuk pengguna * nix tersebut, perhatikan bahwa sebagian besar sistem alias cat to Get-Content, jadi ini biasanya berfungsi

cat ./log.log -Tail 10
George Mauer
sumber
@LauraLiparulo dengan cara apa ini tidak berfungsi? Saya sudah pernah menggunakannya sebelumnya.
George Mauer
4
Saya hanya menggunakannya dan berfungsi tepat dalam format iniGet-Content .\test.txt -Wait -Tail 1
Coops
@LauraLiparulo - Bekerja untuk saya juga:Get-Content -Path .\sync.log -Wait -Tail 10
elika kohen
Di ISE, saya biasa menggunakan while ($ true) / sleep dan beralih ke yang ini, tapi yang ini juga mengunci seluruh ISE dan tidak bisa menjalankan skrip di tab lain. Haruskah saya memulai instance ISE baru?
Teoman shipahi
@ Teomanshipahi Dengan cara apa -Waitparameter tidak berfungsi untuk Anda?
George Mauer
116

Pada PowerShell versi 3.0, cmdlet Get-Content memiliki parameter -Tail yang akan membantu. Lihat bantuan online pustaka technet untuk Get-Content.

Dan Blanchard
sumber
1
Tautan untuk mengunduh di sini - microsoft.com/en-us/download/details.aspx?id=34595 .
Gedrox
4
Catatan untuk beberapa - PS 3.0 tidak tersedia untuk Windows XP dan Vista.
tjmoore
1
Saya menggunakan teknik yang disebutkan oleh Dan tetapi saya mencatatnya dalam $ PROFIL saya. Buka dengan notepad $ PROFIL. Kemudian dalam dokumen teks, buat fungsi baru: function Tail ($ path) {Get-content -tail 15 -path $ path -wait} Dengan cara ini Anda dapat mengakses fungsi setiap kali Anda memulai PowerShell.
Jake Nelson
Ini harus menjadi jawaban yang diterima. -Tunggu bendera yang disebutkan dalam jawaban yang diterima saat ini tidak berfungsi lagi.
Abdullah Leghari
21

Saya menggunakan beberapa jawaban yang diberikan di sini, tetapi hanya untuk itu saja

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

akan mengunyah memori setelah beberapa saat. Seorang kolega meninggalkan "ekor" seperti itu pada hari terakhir dan mencapai 800 MB. Saya tidak tahu apakah Unix tail berperilaku dengan cara yang sama (tapi saya ragu). Jadi tidak apa-apa untuk digunakan untuk aplikasi jangka pendek, tapi hati-hati dengan itu.

John Lockwood
sumber
18

Ekstensi Komunitas PowerShell (PSCX) menyediakan Get-FileTailcmdlet . Sepertinya solusi yang cocok untuk tugas itu. Catatan: Saya tidak mencobanya dengan file yang sangat besar tetapi deskripsi mengatakan itu efisien isi dan dirancang untuk file log besar.

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.
Roman Kuzmin
sumber
1
Ada bug di versi saat ini yang diperbaiki dalam bit harian. Saya akan merekomendasikan mengambil bit terbaru dan mengkompilasinya setidaknya sampai kita mendapatkan versi terbaru yang dirilis.
Keith Hill
7
Versi 2.0 membutuhkan waktu lama untuk menunjukkan 10 baris terakhir file csv 1GB, dan berbeda dari Get-Content [filename] | Select-Object -Last 10itu tidak dapat dibatalkan
Jader Dias
15

Hanya beberapa tambahan pada jawaban sebelumnya. Ada alias yang didefinisikan untuk Get-Content, misalnya jika Anda terbiasa dengan UNIX yang mungkin Anda sukai cat, dan ada juga typedan gc. Jadi, bukannya

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

kamu bisa menulis

# 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
Mikael Sundberg
sumber
3

Menggunakan Powershell V2 dan di bawah ini, get-content membaca seluruh file, jadi tidak ada gunanya bagi saya. Kode berikut berfungsi untuk apa yang saya butuhkan, meskipun ada beberapa masalah dengan pengkodean karakter. Ini secara efektif tail -f, tetapi bisa dengan mudah dimodifikasi untuk mendapatkan x byte terakhir, atau x baris terakhir jika Anda ingin mencari mundur untuk jeda baris.

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

Saya menemukan sebagian besar kode untuk melakukan ini di sini .

hajamie
sumber
1
Benarkah Get-Content dengan opsi -Tail membaca seluruh file? Pada file besar sepertinya OK bagi saya.
Gubernur
Saya percaya itu tergantung pada versi PS. Saya sudah memperbarui jawabannya. Saya terjebak di server tanpa kemampuan untuk menginstal apa pun pada saat itu, jadi kode di atas bermanfaat.
hajamie
3

Saya mengambil solusi @ hajamie dan membungkusnya menjadi pembungkus skrip yang sedikit lebih nyaman.

Saya menambahkan opsi untuk memulai dari offset sebelum akhir file, sehingga Anda dapat menggunakan fungsionalitas seperti ekor untuk membaca jumlah tertentu dari akhir file. Perhatikan offset dalam byte, bukan garis.

Ada juga opsi untuk terus menunggu lebih banyak konten.

Contoh (dengan asumsi Anda menyimpan ini sebagai 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

Dan ini skripnya sendiri ...

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;
    }
}
Brian Reischl
sumber
0

Sangat mendasar, tetapi melakukan apa yang Anda butuhkan tanpa tambahan modul atau persyaratan versi PS:

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

Jesse
sumber
4
Itu brutal pada file besar.
Pecos Bill
Solusi saya adalah: while($true) { Clear-Host; Get-Content <filename> -tail 40; sleep 1 }:)
NoLifeKing
0

Mungkin terlambat untuk menjawab tetapi, coba yang ini

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

Ada banyak jawaban yang valid, namun, tidak satupun dari mereka memiliki sintaks yang sama dengan tail di linux . Fungsi berikut dapat disimpan di $Home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1untuk kegigihan Anda (lihat dokumentasi profil powershell untuk lebih jelasnya).

Ini memungkinkan Anda menelepon ...

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

yang datang cukup dekat dengan sintaks 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
    }
}
Patrick Stalph
sumber