Cbh*_*ihe 5 bash pipe io-redirection process-substitution tee
运行 GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu)。
从有兴趣了解 I/O 处理和相关速度问题的用户的角度来看,我并不真正理解进程替换(ProcSub)。我使用 ProcSub 编写脚本,因此我对文件描述符 0、1、2 有一些了解,但仅此而已。我读过一些不错的帖子,例如[1]和其他。wikis,例如[2],[3],后者说明:“进程替换将一个(或多个进程)的输出(FD 1 和/或 2)馈送到另一个进程的标准输入(FD 0)中”。通过最简单的定义和一个过程,它在操作上似乎与简单的未命名管道没有什么不同。
为了研究这一点,我tee从 i/o 的角度来看,这本身就很有趣。tee允许将"stdin 输入到 stdout 以及作为参数给出的任何文件"。所以 :
$ for i in 1 2 3; do (( j=i+10 )); printf "%d\n" $j > file_$i; done
# so each file in file_{1,2,3} contains the numeral in its name + 10.
$ cat file_{1,2,3} | tee file_4
11
12
13
$ cat file_4
11
12
13
Run Code Online (Sandbox Code Playgroud)
显然,我对看到数据填充我的屏幕 ala Matrix 不感兴趣,所以当:
1)我添加了一个管道和重定向shasum的输出......
$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256
$
Run Code Online (Sandbox Code Playgroud)
上面的一行悄悄退出,file_4 和以前一样(上图),file_4.sha256 包含计算出的 SHA256 和。
以上只是一个例子来说明我的问题,试图理解中间 i/o。我的外行人的结论是,tee将catcmd的输出保存在 file_4 中,其通常发送到 stdout 的副本实际上并未发送到 stdout 而是通过管道传输到shasum.
问:这甚至是远程对吗?
2)我用 ProcSub 尝试同样的方法:
$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
11
12
13
$
Run Code Online (Sandbox Code Playgroud)
-> 发送到 FD 1 的任何内容都没有标准输出重定向tee?
问:我不清楚 ProcSub 对 i/o 做什么或不做什么(显然它在这种情况下不影响 i/o)并且可以使用其机制的解释。
3)我尝试使用 ProcSub 并将最终标准输出重定向到 file_4:
$ cat file_{1,2,3} | tee >(shasum -a 256 > file_4.sha256) > file_4
$
Run Code Online (Sandbox Code Playgroud)
这一次,单线又悄然存在。
问:所以一般的问题是:对于上述 3 种情况(或至少对于第二和第三种情况),i/o 是如何处理的?i/o 术语存在明显和可见的差异(仅查看最终标准输出),但有时不同的 i/o 进程会导致显示器上的最终结果相同。发送。
小智 5
成语>(...)只是手段(以浅白):“该名称的文件”。
它用作“文件名”(有点,一切都会在瞬间清晰):
$ echo <(date)
/proc/self/fd/11
Run Code Online (Sandbox Code Playgroud)
或者您操作系统上的其他一些号码/名称。但是 echo 确实会打印一个名称,就像您这样做一样:
$ echo ProcSubs11
ProcSubs11
Run Code Online (Sandbox Code Playgroud)
如果存在标签为 ProcSubs11 的文件,您还可以执行以下操作:
$ cat ProcSubs11
contents_of_file_ProcSubs11
Run Code Online (Sandbox Code Playgroud)
你可以做同样的事情:
$ cat <(date)
Fri Jan 15 21:25:18 UTC 2016
Run Code Online (Sandbox Code Playgroud)
不同之处在于“进程替换”的实际名称是“不可见的”,并且详细信息比读取一个简单的文件要长得多,正如如何实现进程替换的链接中所有痛苦的细节中所描述的那样在 bash 中?.
说了以上,让我们回顾一下你的项目。
...在操作上似乎与简单的未命名管道没有什么不同......
好吧,“流程替换”完全基于unnamed pipe您给定的第一个链接所述:
- bash 进程创建了一个未命名的管道,用于稍后创建的两个进程之间的通信。
不同的是,所有的6〜步骤在链接说明被简化为一个成语>(...)用于写入和<(...)用于从读出。
并且,可以说连接(管道)有一个名称,就像文件一样。只是该名称对用户隐藏(/proc/self/fd/11在开始时显示)。
1)我添加了一个管道并重定向shasum的输出......
Run Code Online (Sandbox Code Playgroud)$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256
那里没有“进程替换”,但值得注意的是(稍后)tee将其接收stdin到的内容发送(写入)到文件file_4 ,并将相同的stdin内容发送到stdout. 这恰好连接到写入 shasum 的管道(在这种情况下)。
因此,简而言之,通俗地说,将 tee 复制stdin到file_4和shasum。
2)我用 ProcSub 尝试同样的方法:
Run Code Online (Sandbox Code Playgroud)$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
重新使用上面的描述(用外行的话)来描述这个例子:
Tee 复制stdin到三个元素:file_4,shasum和stdout。
为什么?。记住这>(...)是一个文件的名字,让我们把它放在一行中:
$ cat file_{1,2,3} | tee file_4 /proc/self/fd/11
Run Code Online (Sandbox Code Playgroud)
tee 将输入提供给两个文件file_4和shasum(通过“进程替换”)并且stdoutoftee仍然连接到它的默认位置:控制台。这就是您在控制台中看到数字的原因。
为了使这个例子完全等于1),我们可以这样做:
$ cat file_{1,2,3} | tee file_4 > /proc/self/fd/11 ### note the added `>`
Run Code Online (Sandbox Code Playgroud)
这变成了 (是的,必须使用>和 之间的空格>(。
$ cat file_{1,2,3} | tee file_4 > >(shasum -a 256 > file_4.sha256)
Run Code Online (Sandbox Code Playgroud)
那是将tee的标准输出重定向到“进程替换”。
问:所以一般的问题是:上述 3 种情况的 i/o 是如何处理的
我相信我只是解释了 3 种情况,如果不清楚,请发表评论。
为什么 <(...) 构造在第三种情况下不起作用。
因为(通俗地说)您不能将公叉插入公插座。
<(...) 习语从“进程替换”内部读取内容,因此提供“输出”,应插入stdin到外部命令的 中。外部命令tee正在尝试连接stdout(类似)元素。所以,那对无法匹配。
重要说明:
该命令cat在应用于“处理替换”时隐藏了一些细节,因为此命令将提供相同的输出:
$ cat <(date)
$ cat < <(date)
Run Code Online (Sandbox Code Playgroud)
一切都是正确的,但从误导性的平等中得出结论是错误的。