Windows Powershell 中的 Unix tail 等效命令

发布于 2024-10-07 04:20:24 字数 367 浏览 5 评论 0 原文

我必须查看大文件的最后几行(典型大小为 500MB-2GB)。我正在寻找与 Windows Powershell 的 Unix 命令 tail 等效的命令。一些可用的替代方案是

http://tailforwin32.sourceforge.net/

对于

Get-Content [filename] | Select-Object -Last 10

我来说,第一个替代方案是不允许,并且第二种选择很慢。有谁知道 PowerShell 的 tail 的有效实现吗?

I have to look at the last few lines of a large file (typical size is 500MB-2GB). I am looking for an equivalent of the Unix command tail for Windows Powershell. A few alternatives available are,

http://tailforwin32.sourceforge.net/

and

Get-Content [filename] | Select-Object -Last 10

For me, the first alternative is not allowed, and the second alternative is slow. Does anyone know of an efficient implementation of tail for PowerShell?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

娇纵 2024-10-14 04:20:25

为了完整起见,我将提到 Powershell 3.0 现在在 Get-Content 上有一个 -Tail 标志

Get-Content ./log.log -Tail 10

获取文件的最后 10 行

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

获取文件的最后 10 行并等待更多

另外,对于那些 *nix 用户,请注意,大多数系统将 cat 别名为 Get-Content,因此这通常有效

cat ./log.log -Tail 10

For completeness I'll mention that Powershell 3.0 now has a -Tail flag on Get-Content

Get-Content ./log.log -Tail 10

gets the last 10 lines of the file

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

gets the last 10 lines of the file and waits for more

Also, for those *nix users, note that most systems alias cat to Get-Content, so this usually works

cat ./log.log -Tail 10
木森分化 2024-10-14 04:20:25

从 PowerShell 3.0 版开始,Get-Content cmdlet 有一个 -Tail 参数,应该会有所帮助。请参阅Get-Content 的 technet 库联机帮助。

As of PowerShell version 3.0, the Get-Content cmdlet has a -Tail parameter that should help. See the technet library online help for Get-Content.

治碍 2024-10-14 04:20:25

我使用了这里给出的一些答案,但只是一个提示,

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

一段时间后会消耗掉记忆。一位同事在最后一天留下了这样一条“尾巴”,它的大小达到了 800 MB。我不知道 Unix tail 的行为是否相同(但我对此表示怀疑)。所以短期使用是可以的,但是要小心。

I used some of the answers given here but just a heads up that

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

will chew up memory after awhile. A colleague left such a "tail" up over the last day and it went up to 800 MB. I don't know if Unix tail behaves the same way (but I doubt it). So it's fine to use for short term applications, but be careful with it.

风吹雨成花 2024-10-14 04:20:25

对于答案来说可能为时已晚,但是,尝试这个

Get-Content <filename> -tail <number of items (lines) wanted> -wait

Probably too late for an answere but, try this one

Get-Content <filename> -tail <number of items (lines) wanted> -wait
不寐倦长更 2024-10-14 04:20:25

PowerShell 社区扩展 (PSCX) 提供 Get-FileTail cmdlet。它看起来是适合该任务的解决方案。注意:我没有尝试使用非常大的文件,但描述说它可以有效地跟踪内容并且它是为大型日志文件设计的。

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.

PowerShell Community Extensions (PSCX) provides the Get-FileTail cmdlet. It looks like a suitable solution for the task. Note: I did not try it with extremely large files but the description says it efficiently tails the contents and it is designed for large log files.

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.
倾城泪 2024-10-14 04:20:25

只是对之前答案的一些补充。为 Get-Content 定义了别名,例如如果您习惯 UNIX,您可能会喜欢 cat,还有 typegc 。所以

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

Just some additions to previous answers. There are aliases defined for Get-Content, for example if you are used to UNIX you might like cat, and there are also type and gc. So instead of

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

you can write

# 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
长安忆 2024-10-14 04:20:25

关于这个主题,我有一个关于多个文件的有用提示。

使用 PowerShell 5.2(Win7 和 Win10)跟踪单个日志文件(如 Linux 中的“tail -f”)非常简单(只需使用“Get-Content MyFile -Tail 1 -Wait”)。然而,同时查看多个日志文件似乎很复杂。然而,在 PowerShell 7.x+ 中,我通过使用“Foreach-Object -Parrallel”找到了一种简单的方法。这会同时执行多个“获取内容”命令。例如:

Get-ChildItem C:\logs\*.log | Foreach-Object -Parallel { Get-Content $_ -Tail 1 -Wait }

I have a useful tip on this subject concerning multiple files.

Following a single log file (like 'tail -f' in Linux) with PowerShell 5.2 (Win7 and Win10) is easy (just use "Get-Content MyFile -Tail 1 -Wait"). However, watching MULTIPLE log files at once seems complicated. With PowerShell 7.x+ however, I've found an easy way by using "Foreach-Object -Parrallel". This performs multiple 'Get-Content' commands concurrently. For example:

Get-ChildItem C:\logs\*.log | Foreach-Object -Parallel { Get-Content $_ -Tail 1 -Wait }
開玄 2024-10-14 04:20:25

使用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
}

我在此处找到了执行此操作的大部分代码。

Using Powershell V2 and below, get-content reads the entire file, so it was of no use to me. The following code works for what I needed, though there are likely some issues with character encodings. This is effectively tail -f, but it could be easily modified to get the last x bytes, or last x lines if you want to search backwards for line breaks.

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

I found most of the code to do this here.

西瑶 2024-10-14 04:20:25

我采用了 @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;
    }
}

I took @hajamie's solution and wrapped it up into a slightly more convenient script wrapper.

I added an option to start from an offset before the end of the file, so you can use the tail-like functionality of reading a certain amount from the end of the file. Note the offset is in bytes, not lines.

There's also an option to continue waiting for more content.

Examples (assuming you save this as 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

And here is the script itself...

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;
    }
}
新一帅帅 2024-10-14 04:20:25

有很多有效的答案,但是没有一个与 linux 中的 tail.以下函数可以存储在您的 $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
    }
}

There have been many valid answers, however, none of them has the same syntax as tail in linux. The following function can be stored in your $Home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1 for persistency (see powershell profiles documentation for more details).

This allows you to call...

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

which comes quite close to the linux syntax.

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
    }
}
很糊涂小朋友 2024-10-14 04:20:25

尝试Windows Server 2003 Resource Kit Tools

它包含一个可以在Windows系统上运行的tail.exe

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

try Windows Server 2003 Resource Kit Tools

it contains a tail.exe which can be run on Windows system.

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

黒涩兲箜 2024-10-14 04:20:25

非常基本,但无需任何附加模块或 PS 版本要求即可满足您的需求:

while ($true) {Clear-Host; gc E:\test.txt |选择-最后3个;睡眠 2 }

Very basic, but does what you need without any addon modules or PS version requirements:

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

魂牵梦绕锁你心扉 2024-10-14 04:20:25

对于那些遵循“少打字最好”这一公理的管理员来说,这是我能找到的最短版本:

gc filename -wai -ta 10

For those admins who live by the axiom that less typing is best, here is the shortest version I can find:

gc filename -wai -ta 10
那些过往 2024-10-14 04:20:24

-wait 参数与 Get-Content 结合使用,该参数会在行添加到文件时显示行。此功能在 PowerShell v1 中已存在,但由于某种原因在 v2 中没有得到很好的记录。

这是一个示例

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

运行此命令后,更新并保存文件,您将在控制台上看到更改。

Use the -wait parameter with Get-Content, which displays lines as they are added to the file. This feature was present in PowerShell v1, but for some reason not documented well in v2.

Here is an example

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

Once you run this, update and save the file and you will see the changes on the console.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文