处理stdout和stderr分别添加时间戳:错误的顺序

时间:2017-02-05 12:38:27

标签: linux bash unix docker unix-timestamp

这些是我的测试文件:

std-test.sh:

#!/bin/bash
for i in {0..20}
do
    number=$RANDOM
    let "number %= 10"
    if [ $number -le 6 ]
    then
        echo $i;
    else
        echo $i 1>&2;
    fi
done

process.sh:

#!/bin/bash

while read line; do
    [[ $1 = "err" ]] && echo "$(date +%s%3N) $line" >> stderr;
    [[ $1 = "out" ]] && echo "$(date +%s%3N) $line" >> stdout;
done

std-test.sh创建了包含其行号的20行,process.sh能够在管道输出时读取另一个命令输出,而当stderrerr时,它会保存到stdout作为参数传递给它,并在传递out时传递给./std-test.sh 2> >(./process.sh err) > >(./process.sh out)。我用来测试整个事情的命令是: stdout:(摘自here)。我的测试结果如下:

1486297129986 0 1486297129987 1 1486297129988 2 1486297129988 3 1486297129989 4 1486297129990 6 1486297129991 7 1486297129991 8 1486297129992 9 1486297129993 10 1486297129993 11 1486297129994 12 1486297129995 14 1486297129995 17 1486297129996 18

stderr:

1486297129986 5 1486297129987 13 1486297129987 15 1486297129988 16 1486297129989 19 1486297129990 20

stderr

当我尝试解析输出时,我意识到,stdoutstderr的顺序完全搞砸了。例如,为什么stdout中的5位于process.sh中的1之前?或者13岁之后?我在这里犯的错误是什么,我该如何解决呢?

编辑#1:我知道我可以直接将stderr和stdout传输到文件,但{{1}}会将结果卷曲到远程服务器。将其保存到文件只是一种POC。

编辑#2:我实际上是尝试以编程方式为时间戳记和处理泊坞日志。

1 个答案:

答案 0 :(得分:0)

更新

从评论看来,OP确实试图为在docker容器中运行的应用程序添加时间戳并记录输出。

docker logs -t已经做到这一点,并且是最好的工作工具。

原始答案:

可能是因为你为每一行加上时间戳时间戳而不是它们实际生成的时间?

运行该命令时启动3个进程,而不是所有进程并行运行。

进程没有以真正的并行方式运行,只要内核感觉就可以抢占它们。因为stdout更长/处理更多行,所以更有可能被抢占,然后在稍后恢复。这可以解释时间戳。

你真的需要什么时间线上的时间戳?你只想在各行之间进行排序,还是想要真正的真实时间戳?

编辑:正如@Sven Festersen在评论中指出的那样,也可能是因为stdout is buffered when piped by default