uru*_*_na 6 bash tee wc process-substitution
当我在Bash中发出两个等效命令时,我得到了不同的输出(来自"wc -l"命令),见下文:
root@devel:~# ls /usr/bin -lha | tee >(wc -l) >(head) > /dev/null
total 76M
drwxr-xr-x 2 root root 20K Nov 11 18:58 .
drwxr-xr-x 10 root root 4.0K Oct 8 15:31 ..
-rwxr-xr-x 1 root root 51K Feb 22 2017 [
-rwxr-xr-x 1 root root 96 Jan 19 2017 2to3-3.5
-rwxr-xr-x 1 root root 23K Mar 22 2017 addpart
lrwxrwxrwx 1 root root 26 May 10 2017 addr2line -> x86_64-linux-gnu- addr2line
lrwxrwxrwx 1 root root 6 Dec 13 2016 apropos -> whatis
-rwxr-xr-x 1 root root 15K Sep 13 19:47 apt
-rwxr-xr-x 1 root root 79K Sep 13 19:47 apt-cache
137
root@devel:~# ls /usr/bin -lha | wc -l
648
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
这很奇怪,但是当我以这种方式调用它时,它会输出更奇怪的输出:
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root@devel:~# ls /usr/bin -lha | tee >(wc) >(wc -l) > /dev/null
648
root@devel:~# 648 6121 39179
Run Code Online (Sandbox Code Playgroud)
看起来像异步运行的命令,并在不同的时间结束......或者它可以是什么?
怎么修:
ls /usr/bin -lha | tee --output-error=exit-nopipe >(wc -l) >(head) > /dev/null
Run Code Online (Sandbox Code Playgroud)
该命令head仅打印输入的头部,因此只要获得足够的输入就可以完成其工作,然后退出而不等待所有输入.
所以让我们head用简单的命令替换命令"head".
ls /usr/bin -lha | tee >(wc -l) >(read l; echo $l) > /dev/nullRun Code Online (Sandbox Code Playgroud)
simple "head"只读取一行,然后退出,这导致管道文件在tee完成将所有数据传输到它之前立即关闭.
所以毫无疑问,你会得到与简单相同的结果"head".wc仍打印错误的号码.
我认为你可以自己断定问题的根本原因是,其中一个输出管道先tee关闭,tee遇到写入错误,然后停止写入其他输出文件.
在理解了根本原因之后,我认为您将很容易理解手册页中的以下部分.
MODE determines behavior with write errors on the outputs:
'warn' diagnose errors writing to any output
'warn-nopipe'
diagnose errors writing to any output not a pipe
'exit' exit on error writing to any output
'exit-nopipe'
exit on error writing to any output not a pipe
The default MODE for the -p option is 'warn-nopipe'. The default operation
when --output-error is not specified, is to exit immediately on error writing to
a pipe, and diagnose errors writing to non pipe outputs.
Run Code Online (Sandbox Code Playgroud)
实际上,如果您>(wc -l)在有问题的命令行中替换为常规文件,您会发现文件大小始终为16384或20480或32768或36864或28672或...,所有这些都是4096的倍数.(写入常规文件不完整,因为tee之前中止.如果写入完成,文件大小将是任何值.)
4096是PIPE_BUF大多数类UNIX系统的价值.如果您知道什么PIPE_BUF是,您将很容易理解为什么文件大小始终是4096的倍数.