将长标准输出输入tee命令有时会导致截断

lis*_*el1 4 linux bash shell tee

在几个示例中,我可以看到tee不会等待stdout完成,这会导致一些错误的行为。

第一个示例:
seq 50000|tee >(wc) >(head -2) >/dev/null
将输出:

                1
                2
  12773   12774   65536
Run Code Online (Sandbox Code Playgroud)

代替

                1
                2
  50000   50000  288894
Run Code Online (Sandbox Code Playgroud)

第二个示例:
cat f.txt|grep abc|tee f.txt >/dev/null
在此示例中,仅当文件较小时,文件更新才有效,但是如果文件较长,则有时tee会在cat完成之前开始写入,并且文件更新仅在第一个文件中有效“猫”过渡。

您可以说tee仅用于重定向到文件,但我也看到tee的用法。
我知道小便命令没有此错误,但是没有人知道解决办法让tee等待吗?
谢谢 :-)

Kam*_*Cuk 5

您遇到的问题可以简化为:

seq 50000 | tee >(wc) >(exit) >/dev/null
Run Code Online (Sandbox Code Playgroud)

如果其中一个tee写入流返回错误,则tee终止。由于管道通常使用4K缓冲区进行缓冲,因此足以wc抓取一些线并对其进行处理。

head -n2 打印两行后关闭流。

您可以通过告诉tee在错误上打印一些内容来查看错误:

# seq 50000 | tee --output-error=exit >(wc) >(exit) >/dev/null
tee: /dev/fd/62: broken pipe
Run Code Online (Sandbox Code Playgroud)

您可以使用-p或消除问题,或在写入管道时--output-error=warn告知tee错误后继续:

seq 50000 | tee -p >(wc) >(head -n2) >/dev/null
Run Code Online (Sandbox Code Playgroud)

或使用在处理输入后不会退出的命令,例如sed

seq 50000 | tee >(wc) >(sed -n '1,2p') >/dev/null
Run Code Online (Sandbox Code Playgroud)