这些是我的测试文件:
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
能够在管道输出时读取另一个命令输出,而当stderr
为err
时,它会保存到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
当我尝试解析输出时,我意识到,stdout
和stderr
的顺序完全搞砸了。例如,为什么stdout
中的5位于process.sh
中的1之前?或者13岁之后?我在这里犯的错误是什么,我该如何解决呢?
编辑#1:我知道我可以直接将stderr和stdout传输到文件,但{{1}}会将结果卷曲到远程服务器。将其保存到文件只是一种POC。
编辑#2:我实际上是尝试以编程方式为时间戳记和处理泊坞日志。
答案 0 :(得分:0)
更新
从评论看来,OP确实试图为在docker容器中运行的应用程序添加时间戳并记录输出。
docker logs -t
已经做到这一点,并且是最好的工作工具。
原始答案:
可能是因为你为每一行加上时间戳时间戳而不是它们实际生成的时间?
运行该命令时启动3个进程,而不是所有进程并行运行。
进程没有以真正的并行方式运行,只要内核感觉就可以抢占它们。因为stdout更长/处理更多行,所以更有可能被抢占,然后在稍后恢复。这可以解释时间戳。
你真的需要什么时间线上的时间戳?你只想在各行之间进行排序,还是想要真正的真实时间戳?
编辑:正如@Sven Festersen在评论中指出的那样,也可能是因为stdout is buffered when piped by default。