运行 GNU bash,版本 4.3.11(1)-release (x86_64-pc-linux-gnu)。
我不太明白流程替代(ProcSub) 从对 I/O 处理和相关速度问题感兴趣的用户的角度来看。我使用 ProcSub 编写脚本,所以我对文件描述符 0,1,2 有一些了解,但仅此而已。我读过一些不错的帖子,例如[1]和杂项。维基百科,例如[2],[3],后者指出:“进程替换将一个进程(或多个进程)的输出(FD 1 和/或 2)送入另一个进程的 stdin (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
显然,我对看到数据填充我的屏幕ala Matrix不感兴趣,所以当:
1)我添加了一个管道并重定向了shasum
输出...
$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256
$
上面的一张班轮出口悄悄、 file_4 与之前(上面)一样,并且 file_4.sha256 包含计算出的 SHA256 和。
上面只是一个例子来说明我的问题,试图理解中间 i/o。我的外行人的结论是,将 cmdtee
的输出保存cat
在 file_4 中,并且通常发送到 stdout 的副本实际上不是发送到 stdout 而是通过管道传输到shasum
.
问:这完全正确吗?
2)我用 ProcSub 尝试同样的操作:
$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
11
12
13
$
-> 发送到 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
$
这一次,俏皮话又悄然存在。
问:所以一般问题是:上面的 3 种情况(或者至少是第二种和第三种情况)的 i/o 是如何处理的? I/O 术语存在明显可见的差异(仅查看最终的标准输出),但有时不同的 I/O 进程可能会导致显示上相同的最终结果。德克萨斯州。
答案1
这个成语的>(...)
意思只是(通俗地说):“姓名一个文件”。
它充当“文件名”(某种程度上,一切都会立即清晰):
$ echo <(date)
/proc/self/fd/11
或者您操作系统上的其他数字/名称。但 echo 确实打印了一个名字,就像你所做的一样:
$ echo ProcSubs11
ProcSubs11
如果存在带有标签 ProcSubs11 的文件,您还可以执行以下操作:
$ cat ProcSubs11
contents_of_file_ProcSubs11
你可以做同样的事情:
$ cat <(date)
Fri Jan 15 21:25:18 UTC 2016
不同之处在于,“进程替换”的实际名称是“不可见的”,并且详细信息比读取简单文件要长得多,正如链接中所有痛苦细节中所描述的那样bash 中是如何实现进程替换的?。
说了上面的内容,让我们回顾一下您的项目。
问1
...在操作上似乎与简单的无名管道没有什么不同...
好吧,“过程替换”完全基于unnamed pipe
您给定的第一个链接状态:
- bash 进程创建一个无名管道,用于稍后创建的两个进程之间的通信。
不同之处在于,链接中解释的所有 ~6 个步骤都被简化为一个惯用>(...)
语写信给并<(...)
为读自。
并且,可以说连接(管道)有一个名称,就像文件一样。只是该名称对用户隐藏(/proc/self/fd/11
如开头所示)。
实施例1
1)我添加了一个管道和shasum输出的重定向......
$ 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
2)我用 ProcSub 尝试同样的操作:
$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
重新使用上面的描述(通俗地讲)来描述这个例子:
T 恤复制stdin
到三个元素:file_4
、shasum
和stdout
。
为什么?。请记住这>(...)
是一个文件的名称,让我们将其放入行中:
$ cat file_{1,2,3} | tee file_4 /proc/self/fd/11
tee 正在将输入提供给两个文件file_4
and shasum
(通过“进程替换”),并且stdout
oftee
仍然连接到其默认位置:控制台。这就是您在控制台中看到数字的原因。
为了使这个例子完全等于1),我们可以这样做:
$ cat file_{1,2,3} | tee file_4 > /proc/self/fd/11 ### note the added `>`
这变成(是的,必须使用>
和 之间的空格。>(
$ cat file_{1,2,3} | tee file_4 > >(shasum -a 256 > file_4.sha256)
这就是tee
将 的标准输出重定向到“进程替换”。
问3
问:所以普遍的问题是:对于上面的3种情况,i/o是如何处理的
我相信我只是解释了这3个案例,如果不清楚,请评论。
问题 4(请在评论中编辑并添加问题)
为什么 <(...) 构造在第三种情况下不起作用。
因为(通俗地说)你不能插入公插脚插入公插座。
<(...) 习语从“进程替换”内部读取内容,因此提供“输出”,应插入到stdin
外部命令中。外部命令tee
正在尝试连接stdout
(类似)元素。所以,这一对无法匹配。
一个重要的笔记:
该命令cat
在应用于“进程替换”时隐藏了一些细节,因为这两个命令将给出相同的输出:
$ cat <(date)
$ cat < <(date)
一切都是正确的,但从误导性的等式中得出结论是错误的。
答案2
它在操作上似乎与简单的无名管道没有什么不同。
关键是并非每个软件都支持从 stdin 读取或写入 stdout。
此外,如果您想要来自多个进程的输入,那么您无法仅用管道来区分它们(不查看数据本身):
{ echo foo; echo bar; } | cat
# vs.
cat <(echo foo) <(echo bar)
显然cat
是一个坏例子。但有了awk
它就可以有所作为(FNR
对比NR
)。
2)
tee file_4 >(shasum -a 256 > file_4.sha256)
发送到 FD 1 的任何内容都没有标准输出重定向
tee
?
不,为什么要有?>(cmd)
做不是意思是“重定向标准输出”!所以就有了一个不带重定向的命令。以防万一3)您向命令添加重定向,并且输出被重定向。
您可以使用它来更好地理解命令行:
echo tee file_4 >(shasum -a 256 > file_4.sha256)