【问题标题】:How do I add timestamps to individual lines of PowerShell & output?如何将时间戳添加到 PowerShell 和输出的各个行?
【发布时间】:2014-12-08 15:40:13
【问题描述】:

如果有的话,如何为& PowerShell 运算符生成的输出的每一行添加时间戳?

例子:

PS H:\> $result = & ping 192.168.1.1
PS H:\> echo $result

Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time=104ms TTL=250
Reply from 192.168.1.1: bytes=32 time=106ms TTL=250
Reply from 192.168.1.1: bytes=32 time=102ms TTL=250
Reply from 192.168.1.1: bytes=32 time=102ms TTL=250
Ping statistics for 192.168.1.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 102ms, Maximum = 106ms, Average = 103ms

想要的结果:

PS H:\> echo $result

2014-12-08T14:45:48.8898125+00:00:Pinging 192.168.1.1 with 32 bytes of data:
2014-12-08T14:45:48.8932661+00:00:Reply from 192.168.1.1: bytes=32 time=104ms TTL=250
2014-12-08T14:45:48.9233451+00:00:Reply from 192.168.1.1: bytes=32 time=106ms TTL=250
2014-12-08T14:45:48.9765438+00:00:Reply from 192.168.1.1: bytes=32 time=102ms TTL=250
2014-12-08T14:45:49.0233105+00:00:Reply from 192.168.1.1: bytes=32 time=102ms TTL=250
2014-12-08T14:45:49.0233201+00:00:
2014-12-08T14:45:49.0238753+00:00:Ping statistics for 192.168.1.1:
2014-12-08T14:45:49.0239210+00:00:    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
2014-12-08T14:45:49.0233318+00:00:Approximate round trip times in milli-seconds:
2014-12-08T14:45:49.0237209+00:00:    Minimum = 102ms, Maximum = 106ms, Average = 103ms

我知道如何拆分/加入 PowerShell 数组,但这只能在 & 运算符完成后发生。我正在寻找更多类似实时的解决方案,在 & 运算符运行时将时间戳添加到输出中。

顺便说一下,时间戳本身是$($(Get-Date -Format o) + ":")

【问题讨论】:

    标签: datetime powershell logging process


    【解决方案1】:

    您可以使用过滤器:

    filter timestamp {"$(Get-Date -Format o): $_"}
    $result = & ping 192.168.1.1 | timestamp
    

    $result 的示例输出:

    2014-12-08T11:42:59.2827202-05:00: 
    2014-12-08T11:42:59.2857205-05:00: Pinging 192.168.1.1 with 32 bytes of data:
    2014-12-08T11:43:03.1241043-05:00: Request timed out.
    2014-12-08T11:43:08.1236042-05:00: Request timed out.
    2014-12-08T11:43:13.1241042-05:00: Request timed out.
    2014-12-08T11:43:18.1246042-05:00: Request timed out.
    2014-12-08T11:43:18.1246042-05:00: 
    2014-12-08T11:43:18.1246042-05:00: Ping statistics for 192.168.1.1:
    2014-12-08T11:43:18.1246042-05:00:     Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),
    

    【讨论】:

    • 我的问题首先是关于如何将时间戳添加到输出中,而不是如何随后将它们过滤(或过滤)。
    • 这就是过滤器的作用。 PowerShell 过滤器是一个脚本块,它接受来自管道的输入,并针对从管道获取的每个对象运行一次。它在功能上与只有一个 Process 块的函数相同。该过滤器会将时间戳添加到可执行文件的每一行输出中。
    • 啊,确实,它确实像您描述的那样工作。谢谢一百万 - 问题解决了!
    【解决方案2】:

    对于正在寻找有关filterhere is the documentation 的更多信息的任何人。很难找到,因为搜索“filter”和“powershell”这个词的任何组合都会给出一百万个示例并且没有文档。此外,powershell 中的 help filter 也没有提供明显的帮助。

    mjolinor 提供的答案是执行此类操作的最佳方式,但我想对其进行扩展。

    filter timestamp {"$(Get-Date): $_"}
    

    是调用这个的快捷方式

    function timestamp { Process{"$(Get-Date): $_"} }
    

    这两者都创建了接受来自管道的输入的命名函数。在 powershell 中运行 help pipline 以了解更多信息。管道将一次对单个对象进行操作,并且可以使用 automatic variable $_ 引用该对象。因此,每个函数都将遍历管道中使用| 管道字符传递给它的每个项目。

    这与普通函数的行为不同,因为它在对象到达时对其进行处理,而不是一次全部处理。例如运行

    function timestamp {
            "$(Get-Date): $input"
    }
    $result = & ping 127.0.0.1
    $result | timestamp
    

    会将整个 $result 对象转储到一行中并产生如下所示的响应

    03/14/2018 15:23:16:  Pinging 127.0.0.1 with 32 bytes of data: Reply from 127.0.0.1: b
    ytes=32 time<1ms TTL=128 Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 Reply from 12
    7.0.0.1: bytes=32 time<1ms TTL=128 Reply from 127.0.0.1: bytes=32 time<1ms TTL=128  Pi
    ng statistics for 127.0.0.1:     Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 
    Approximate round trip times in milli-seconds:     Minimum = 0ms, Maximum = 0ms, Avera
    ge = 0ms
    

    由于该函数作为一个整体对对象进行操作,因此您必须遍历每一行。改成这个

    function timestampfunction {
        foreach ($i in $input){
            "$(Get-Date): $i"
        }
    }
    

    会给你格式很好的

    03/14/2018 15:23:16: 
    03/14/2018 15:23:16: Pinging 127.0.0.1 with 32 bytes of data:
    03/14/2018 15:23:16: Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    03/14/2018 15:23:16: Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    03/14/2018 15:23:16: Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    03/14/2018 15:23:16: Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
    03/14/2018 15:23:16: 
    03/14/2018 15:23:16: Ping statistics for 127.0.0.1:
    03/14/2018 15:23:16:     Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    03/14/2018 15:23:16: Approximate round trip times in milli-seconds:
    03/14/2018 15:23:16:     Minimum = 0ms, Maximum = 0ms, Average = 0ms
    

    Here 是一篇写得很好的文章,介绍了这些方法之间的差异。

    【讨论】:

      【解决方案3】:

      您可以只使用ForEach-Object cmdlet(在下面的示例中使用% 别名)

      ping 192.168.1.1 | %{ "{0:HH:mm:ss:fff}: {1}" -f (Get-Date), $_ }
      

      结果:

      23:41:51:301:
      23:41:51:302: Pinging 192.168.1.1 with 32 bytes of data:
      23:41:55:255: Request timed out.
      23:42:00:266: Request timed out.
      23:42:05:254: Request timed out.
      23:42:10:253: Request timed out.
      23:42:10:261:
      23:42:10:263: Ping statistics for 192.168.1.1:
      23:42:10:265:     Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),
      

      或者使用类似 mjolinor 的格式回答:

      ping 192.168.1.1 | %{ "{0:o}: {1}" -f (Get-Date), $_ }
      

      结果:

      2019-04-23T23:45:40.5816185+02:00:
      2019-04-23T23:45:40.5845856+02:00: Pinging 192.168.1.1 with 32 bytes of data:
      2019-04-23T23:45:44.2560567+02:00: Request timed out.
      2019-04-23T23:45:49.2549104+02:00: Request timed out.
      2019-04-23T23:45:54.2547535+02:00: Request timed out.
      2019-04-23T23:45:59.2547932+02:00: Request timed out.
      2019-04-23T23:45:59.2577788+02:00:
      2019-04-23T23:45:59.2607707+02:00: Ping statistics for 192.168.1.1:
      2019-04-23T23:45:59.2627647+02:00:     Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),
      

      【讨论】:

      • 这可能是让事情顺利进行的最短的代码。我坚持使用 mjolinor 的解决方案,因为它更适合我(更大的代码库、多个脚本等,因此代码可重用性对我很重要)
      【解决方案4】:

      您可以将 Start-Transcript cmdlet 与配置文件中的自定义提示结合使用:

      # Configure PS prompt to show date and time
      function prompt
      { 
          $promptStringStart = "PS:" + (Get-Date -format MM/dd/yy` hh:mm:ss)
          $promptStringEnd += ">"
          Write-Host $promptStringStart -NoNewline -ForegroundColor Yellow
          Write-Host $promptStringEnd -NoNewline -ForegroundColor Yellow
          return " "
      }
      

      这在我的 Windows 7 工作站上运行良好。但是,在一些较新的 Server 2012 R2 安装上,Start-Transcript 似乎略有损坏。这修复了部分问题:https://support.microsoft.com/en-us/help/3014136/powershell-transcript-file-doesn-t-contain-the-correct-information-in-windows-server-2012-r2

      ...但它仍然无法解决自定义提示的问题。

      例如,我在控制台上看到了这个:

      PS:02/14/17 08:28:20> hostname
      server463
      

      这就是写入日志的内容:

      PS:02/14/17 08:28:20
      >
      
      PS>hostname
      server463
      

      【讨论】:

      • 谢谢,这是一个非常有趣的方法,我相信它在某些情况下很有用。尽管按照上面 mjolinor 的回答,我坚持使用时间戳过滤器方法。更适合我的需要。
      猜你喜欢
      • 2014-01-01
      • 1970-01-01
      • 2020-03-29
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      • 2017-02-04
      • 2023-03-31
      相关资源
      最近更新 更多