在_进程替换_上下文中理解 i/o 重定向

在_进程替换_上下文中理解 i/o 重定向

运行 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您给定的第一个链接状态:

  1. 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 复制stdinfile_4shasum

实施例2

2)我用 ProcSub 尝试同样的操作:

$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)

重新使用上面的描述(通俗地讲)来描述这个例子:

T 恤复制stdin到三个元素:file_4shasumstdout

为什么?。请记住这>(...)是一个文件的名称,让我们将其放入行中:

$ cat file_{1,2,3} | tee file_4 /proc/self/fd/11

tee 正在将输入提供给两个文件file_4and shasum(通过“进程替换”),并且stdoutoftee仍然连接到其默认位置:控制台。这就是您在控制台中看到数字的原因。

为了使这个例子完全等于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)

相关内容