bash如何对待“>>()”


9

在尝试输出重定向和进程替换时,我偶然发现了以下命令及其结果输出:

    me @ elem:〜$ echo foo>>(cat); 回声条
    酒吧
    me @ elem:〜$ foo

(是的,最后的空换行是有意的。)

因此,bash echo的栏会显示我通常的提示,echo的foo,echo的换行符,然后将光标留在那里。如果再次按下Enter键,它将在新行上打印提示,并将光标留在它的后面(按预期,当有人在空命令行上按下Enter键时)。

我期望它将foo写入文件描述符,cat读取它并回显foo,第二个回显回显的栏,然后返回命令提示符。但这显然不是事实。

有人可以解释发生了什么吗?


我想建议您查看以下答案:unix.stackexchange.com/questions/182800/…它解释了双重重定向,并解释了为什么会有不同的结果。穆鲁和迈克尔·霍默斯。
没时间

有关明确地解释为什么在某些版本的Bourne Again shell中提示后出现过程替换输出的问题(在某些情况下根本不出现),请参见unix.stackexchange.com/questions/471987
JdeBP

Answers:


9

根据时间的不同,您可能会看到foo显示在提示之前bar,之后bar,甚至之后。添加一些延迟以获得一致的时间:

$ echo foo > >(sleep 1; cat); echo bar; sleep 2 
bar
foo
$

bar立即出现,然后foo在一秒钟后出现,然后在下一秒钟后出现下一个提示。

发生的是bash在后台执行进程替换。

  1. 主bash进程启动要执行的子shell sleep 1; cat,并为其建立管道。
  2. bash主进程执行echo foo。由于这不会填满管道的缓冲区,因此该echo命令将终止而不会阻塞。
  3. bash主进程执行echo bar
  4. bash主进程将启动命令sleep 2
  5. 同时,subshel​​l正在启动命令sleep 1
  6. 大约1秒钟后,sleep 1返回子流程。子流程继续执行cat
  7. cat 将其输入复制到其输出(显示在屏幕上)并返回。
  8. 子外壳已完成工作,然后退出。
  9. 再过一秒钟,sleep 2返回。主shell进程完成执行,您会看到下一个提示。

3

您不需要流程替代即可获得这种效果。尝试这个:

( echo foo | cat & )

由于相同的原因,您将获得几乎相同的结果(不使用bar;我将其保留为练习)。在这两种情况下,cat都是作为后台任务启动的。在我这里,这很明显。在流程替换的情况下,它也是显式的-它是一个附加到名称文件描述符的单独的流程-但它可能不那么明显。

子进程不一定会在bash打印下一个提示之前终止。并且由于其输出已缓冲,因此在终止之前不会输出任何内容。那时,bash刚$在stderr上打印,现在后台进程在打印foo并换行后退出。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.