【问题标题】:Unix tail equivalent command in Windows PowershellWindows Powershell 中的 Unix 尾部等效命令
【发布时间】:2011-05-24 12:14:22
【问题描述】:

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

http://tailforwin32.sourceforge.net/

获取内容 [文件名] | Select-Object -Last 10

对我来说,不允许使用第一种方案,第二种方案很慢。有谁知道 PowerShell 的 tail 的有效实现。

【问题讨论】:

标签: windows powershell tail


【解决方案1】:

-wait 参数与Get-Content 一起使用,它会在添加到文件时显示行。此功能在 PowerShell v1 中提供,但由于某种原因在 v2 中没有很好地记录。

这是一个例子

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

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

【讨论】:

  • 有趣。我原以为所有存在的参数也会出现在帮助中,但man gc -par wait 告诉我没有参数。但我认为这并不能解决 OP 的问题,因为他们要求 tail,而不是 tail -f 以及有效的实施。由于这个文件在返回最后几行之前也会读取完整的文件,这对于他们期望的文件大小来说是很痛苦的。
  • 仅供参考,这就是 PSCX 中的 Get-FileTail(别名 tail)实现。好奇的可以看源码:pscx.codeplex.com/SourceControl/changeset/view/78514#1358075
  • @Joey -Wait 是一个动态参数,仅适用于文件系统提供程序。 GC 可用于任何实现该 API 的提供程序。除了文档,我知道发现这些的唯一方法是使用 (gcm Get-Content).Parameters 从适当的提供程序路径中。不要使用别名“gc”,因为动态参数不会显示出来。
  • 我知道这是不久前的事了,但这需要写入文件的进程在 Get-Content 工作之前打开、附加、关闭它。如果写入过程从不关闭文件,那么它将无法工作,而 tail -f 则不是这样。
  • 奇怪的是,-Wait 仅在我以某种方式访问​​日志文件时(例如在 Windows 资源管理器中选择它)显示新行。当新行写入我的文件时,Tail 会提供更新。使用 -Wait,我可以愉快地打开一个 PowerShell 窗口,在写入文件时不显示任何新行。如果我然后弹出并单击 Windows 资源管理器中的文件,PowerShell 突然“唤醒”并赶上剩余的行。这是一个错误吗?
【解决方案2】:

为了完整起见,我会提到 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

【讨论】:

  • @LauraLiparulo 这在什么方面不起作用?我以前肯定用过。
  • 我刚刚使用它,它以这种格式在Get-Content .\test.txt -Wait -Tail 1
  • @LauraLiparulo - 也适合我:Get-Content -Path .\sync.log -Wait -Tail 10
  • 在 ISE 上,我曾经使用 while($true)/sleep 并切换到这个,但是这个也锁定了整个 ISE,无法在其他选项卡上运行脚本。我应该启动一个新的 ISE 实例吗?
  • @Teomanshipahi -Wait 参数对您不起作用?
【解决方案3】:

从 PowerShell 3.0 版开始,Get-Content cmdlet 有一个 -Tail 参数应该会有所帮助。见the technet library online help for Get-Content.

【讨论】:

  • 一些注意事项 - PS 3.0 不适用于 Windows XP 和 Vista。
  • 我使用了 Dan 提到的技术,但我将它记录在我的 $PROFILE 中。用记事本 $PROFILE 打开它。然后在文本文档中,新建一个函数: function Tail ($path) { Get-content -tail 15 -path $path -wait } 这样每次启动PowerShell就可以访问到这个函数了。
  • 这应该是公认的答案。 - 当前接受的答案中提到的等待标志不再起作用。
【解决方案4】:

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

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

一段时间后会占用内存。一位同事在最后一天留下了这样一个“尾巴”,它上升到了 800 MB。我不知道 Unix tail 的行为是否相同(但我对此表示怀疑)。所以它可以用于短期应用程序,但要小心。

【讨论】:

    【解决方案5】:

    PowerShell Community Extensions (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.
    

    【讨论】:

    • 当前版本中存在一个已在每日位中修复的错误。我建议至少在我们发布更新版本之前获取最新的位并编译它们。
    • 2.0 版需要很长时间才能显示 1GB csv 文件的最后 10 行,并且与 Get-Content [filename] | Select-Object -Last 10 不同,它不能中止
    【解决方案6】:

    只是对先前答案的一些补充。为 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
    

    【讨论】:

      【解决方案7】:

      可能为时已晚,但是,试试这个

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

      【讨论】:

      • 这些都没有跟随选项。这是使用tail 命令的 99% 用例。
      • @Andries 你看到 Ravikanth 的回答了吗?您可以使用-Wait 关注。
      • 添加了@JasonS 建议的标志
      【解决方案8】:

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

      我找到了大部分代码来执行此操作here

      【讨论】:

      • 带有 -Tail 选项的 Get-Content 是否会读取整个文件?在大文件上对我来说似乎没问题。
      • 我相信这取决于PS版本。我已经更新了答案。我当时被困在无法安装任何东西的服务器上,所以上面的代码很有用。
      【解决方案9】:

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

      【讨论】:

        【解决方案10】:

        试试Windows Server 2003 Resource Kit Tools

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

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

        【讨论】:

          【解决方案11】:

          有很多有效的答案,但是没有一个与tail in linux 具有相同 语法。以下函数可以存储在您的$Home\Documents\PowerShell\Microsoft.PowerShell_profile.ps1 中以实现持久性(请参阅powershell profiles documentation 了解更多详细信息)。

          这允许您调用...

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

          【讨论】:

            【解决方案12】:

            可以从这个 GitHub 存储库下载为 Windows 编译的所有 UNIX 命令:https://github.com/George-Ogden/UNIX

            【讨论】:

            • 你好。欢迎来到 SO。在回答问题之前,请注意其他 12 个答案,其中 3 个的分数超过 100。
            【解决方案13】:

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

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

            【讨论】:

            • 这对大文件来说太残忍了。
            • 我的解决方法是:while($true) { Clear-Host; Get-Content &lt;filename&gt; -tail 40; sleep 1 } :)
            【解决方案14】:

            我有一个关于多个文件的有用提示。

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

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

            【讨论】:

              猜你喜欢
              • 2018-01-11
              • 1970-01-01
              • 2011-12-26
              • 2015-07-15
              • 2010-09-16
              • 2016-10-02
              • 2013-07-08
              • 1970-01-01
              相关资源
              最近更新 更多