在zsh中,cat <(cat)与cat |之间的区别 猫vs猫=(猫)?


18

我期望cat <(cat)cat | cat做同样的事情:将行从stdin复制到stdout。我的理解是,两者都将cat在子shell中执行一个,将子shell cat的stdout 重定向到一个临时的命名管道,然后cat在当前shell中执行另一个,将其stdin重定向到该管道。

取而代之的是cat <(cat)让我在终端上键入内容,但是没有任何输入行被复制并且^D无法发出信号EOFcat | cat工作正常。

作为进一步的实验,我检查了是否cat =(cat)有与相似的困难cat <(cat),但是它按我的预期工作:一次将所有stdin直到一个^Dget都复制到stdout。

谁能帮助我了解zsh的功能?

Answers:


23
  1. a | b所连接STDOUT距离aSTDIN距离b只需使用dup/dup2。这两个命令是并行执行的。

  2. a =(b)将参数to替换为a临时文件名。b将在之前执行,a因为需要先创建临时文件,然后才能将其传递给a

  3. a <(b)a命名管道替换参数。ab并行运行。现在这变得有些复杂了:

    b在后台,无法从终端读取。您可以通过strace -p $PID附加到第二个cat进程来查看该进程,从而自己进行测试。

    a在此期间,尝试从命名管道中读取内容,但无法读取,因为b无法读取。

    •这意味着您基本上有一个死锁,在其中a尝试读取bb无法读取STDIN和写入的死锁a

来自man bash的有关后台进程和终端的更多信息:

为了便于用户界面实现作业控制,操作系统保留了当前终端进程组ID的概念。该进程组的成员(进程组ID等于当前终端进程组ID的进程)接收键盘生成的信号,例如 SIGINT。据说这些过程是前台背景进程是指进程组ID与终端不同的进程;这样的过程不受键盘产生的信号的影响。仅前台进程被允许读取,或者,如果用户如此指定要停止,则可以写入终端。内核终端驱动程序向尝试从终端读取(写到stty tostop生效时写入)的后台进程发送了SIGTTIN(SIGTTOU)信号,除非捕获该进程,否则它将挂起该进程。


太好了,谢谢您-这已经清除了很多!
艾伦·奥唐奈

1
请注意,当非交互式时,zsh将后台命令的标准输入(包括中的命令<(cmd))重定向到/dev/null,因此行为有所不同(zsh -c 'cat <(cat)'立即返回并且不输出任何内容)。
斯特凡Chazelas
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.