我正在尝试通过以下方式在文件的每一行输出前添加一些信息:
这是我的测试脚本:
#!/bin/bash
#
# Test proxying stdout and stderr
#
function proxy-stdouterr() {
local name="$1"
local handle=$2
while IFS='' read -r line
do
echo -e "[ ${name}: ${line} ]" >&${handle}
done
}
# Output some messages and attempt to parse them
(
echo "1: Normal message"
echo "2: Error" >&2
echo "3: Normal message"
echo "4: Error" >&2
) 2> >(proxy-stdouterr "stderr" 2) > >(proxy-stdouterr "stdout" 1)
这种方法效果很好但不保留终端中的顺序(Ubuntu 12.04)。
不代理输出时:
1: Normal message
2: Error
3: Normal message
4: Error
然而,代理订单时并未保留。更糟糕的是,这不是确定性的,大部分时间都是:
[ stderr: 2: Error ]
[ stderr: 4: Error ]
[ stdout: 1: Normal message ]
[ stdout: 3: Normal message ]
但偶尔:
[ stderr: 2: Error ]
[ stdout: 1: Normal message ]
[ stderr: 4: Error ]
[ stdout: 3: Normal message ]
我该如何解决这个问题?
由于
答案 0 :(得分:1)
正如其他人所说,这是一个没有明显的同步问题 回答时不知道你特别控制哪些部分 并希望改变。
恕我直言有两个主要攻击面:
流缓冲。大多数C派生程序不缓冲stderr,
如果它们是终端和缓冲区,则按行缓冲stdin和stdout
完全不然。这就解释了为什么斯特德尔总是会来
在你的例子中首先。廉价的警察是使用/usr/bin/echo
而不是内置echo
,所以你最后得到一个刷新的流
每一行(以及过程产生的大量延迟)。它解决了
你的例子100%是我尝试过的,所以对你来说已经足够了
太。如果您对生成线条的命令有控制权,
确保stdout和stderr都是行缓冲的。
进程安排。您有两个竞争过程的进程
两个流。如果当时有数据流动,
他们互相竞争。你可以减轻它
只有一个过程可以做到这一点,但我不确定它是否可行
保持原生bash
的效率(无可编程POSIX select
最终用户可以使用)
在任何情况下,如果在图片中的任何地方排队,那么你就是 在保持秩序的情况下搞砸了。