【问题标题】:How to add timestamp while redirecting stdout to file in Bash?如何在将标准输出重定向到 Bash 中的文件时添加时间戳?
【发布时间】:2014-02-01 14:49:16
【问题描述】:

我有一个程序(服务器),我正在寻找一种方法(脚本),它将所有 stdout 重定向(或更好地复制)到文件并为每个条目添加时间戳。

我做了一些研究,我能得到的最大收获是感谢How to add timestamp to STDERR redirection。它重定向stdout,但添加的时间戳是脚本完成的时间:

#!/bin/bash
./server | ./predate.sh > log.txt

predate.sh的代码:

#!/bin/bash
while read line ; do
    echo "$(date): ${line}"
done

似乎在程序退出后服务器输出被刷新。(没有重定向它工作正常)。此外,如果我尝试在提到的线程中的给定示例上使用predate.sh,它会完美运行。我知道向主程序添加时间戳很容易,但我宁愿避免编辑其代码。

【问题讨论】:

  • 那么问题是所有的时间戳都是一样的,脚本完成的时间?听起来这是server 输出未正确缓冲的问题。 stackoverflow.com/questions/3465619/… 可能就是你要找的东西
  • 管道输出到 awk。它提供了一个名为strftime的函数。
  • expect 发行版附带一个名为 unbuffer 的程序:unbuffer ./server | ./predate.sh > log.txt
  • 另见 man stdbuf
  • 如果您在链接问题中尝试丹尼斯的解决方案,您会得到什么?例如./server.sh > >( ./predate.sh > log.txt )

标签: linux bash redirect


【解决方案1】:

我最近确实需要:在串行控制台 (picocom) 中接收日志消息,将它们打印到终端和文件中,然后添加日期。

我现在用的看起来……像这样:

picocom -b 115200 /dev/tty.usbserial-1a122C | awk '{ print strftime("%s: "), $0; fflush(); }' | tee serial.txt
  • picocom 的输出通过管道传送到awk
  • awk 前置日期(%s 选项将时间转换为 自 1970-01-01 00:00:00 UTC 以来的秒数 - 或使用 %c 进行人类可读格式)
  • fflush() flushes any buffered outputawk
  • 通过管道传送到tee,将其转移到文件中。 (你可以找到一些关于 tee here 的东西)

【讨论】:

  • 非常感谢您。我想添加到使用它的任何人,以打印类似“2015-11-13 17:04:57:”的时间戳,模式为“%Y-%m-%d %H:%M:%S: "。
  • Awk,永远来救援。
  • 这是我唯一的输出:awk: line 2: function strftime never defined
  • @ygoe,你用的是什么版本的 awk?
【解决方案2】:

moreutils ts

绝对日期和时间是默认值:

$ sudo apt-get install moreutils
$ (echo a;sleep 1;echo b;sleep 3;echo c;sleep 2;echo d;sleep 1) | ts | tee myfile
$ cat myfile
Apr 13 03:10:44 a
Apr 13 03:10:45 b
Apr 13 03:10:48 c
Apr 13 03:10:50 d

或从ts -s开始的程序开始计数:

$ (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2; echo d; sleep 1) | ts -s
00:00:00 a
00:00:01 b
00:00:04 c
00:00:06 d    

或使用ts -i 进行基准测试的增量:

$ (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2; echo d; sleep 1) | ts -i
00:00:00 a
00:00:01 b
00:00:03 c
00:00:02 d
$ (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2; echo d; sleep 1) | ts -i '%.s'
0.000010 a
0.983308 b
3.001129 c
2.001120 d

另请参阅:How to monitor for how much time each line of stdout was the last output line in Bash for benchmarking?

在 Ubuntu 18.04、moreutils 0.60 上测试。

【讨论】:

    【解决方案3】:

    对我来说,您的代码运行良好

    检查这是我尝试过的

    test.sh

    #!/bin/bash
    
    while true; do
      echo "hello"
    done
    

    predate.sh

    #!/bin/bash
    
    while read line; do
      echo $(date) ":" $line;    
    done
    

    然后

    ./test.sh  | ./predate.sh
    

    给我

    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    Tue Jan 14 17:49:47 IST 2014 : hello
    

    可以使用“>”或“>>”将其重定向到某个文件以进行附加

    【讨论】:

    • 如果您仔细阅读我的问题 - 这是可行的。脚本的标准输出为我工作,但程序的标准输出没有(奇怪)。我需要程序的标准输出。这个问题比简单地重定向输出更复杂 - 程序的输出在结束后立即被刷新。
    • 格式丢失:我努力使格式正确,最终得到了这个function predate () { tr "\n" "\0" | xargs -0 -I{} echo "$(date) : {}"; }(请注意,这仍然不能回答问题)。
    【解决方案4】:

    同样,使用 moreutils 中的 ts,您可以在脚本顶部使用 exec。

    #!/bin/bash
    
    exec > >(ts>>file.log)
    
    echo hello 1
    echo hello 2
    sleep 5
    echo hello 3
    

    【讨论】:

      【解决方案5】:

      如果我理解您的问题是将 stderr 输出包含在您的 log.txt 文件中。正确的 ? 如果这就是您想要的解决方案是:

      ./服务器 2>&1 | ./predate.sh > log.txt

      问候

      【讨论】:

      • 可能你的服务器执行太快了...尝试按如下方式打印纳秒并检查差异: echo "$(date +%T.%N): ${line}"
      • 我有关闭服务器的功能,需要 25 秒,相信我 - 我会注意到...
      • 当然,但是您的服务器可能会非常快速地打印一些行并停止打印任何内容,直到它结束...在您的 predate.sh 脚本中添加开始和结束消息。
      猜你喜欢
      • 1970-01-01
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      相关资源
      最近更新 更多