简单的 cat echo 进程替换挂起

简单的 cat echo 进程替换挂起

用 cat 进行简单的进程替换似乎挂起:

cat >( echo hello; )

永远不会结束。还尝试过:

cat >( echo hello; exit; )

从子进程手动关闭标准输出文件描述也不起作用:

cat >( echo hello; 1>&- )
cat >( echo hello; 1>&- exit; )

我尝试过 GNU bash,版本 4.4.23(1)-release,GNU bash,版本 4.1.2(2)-release 和 zsh 5.5.1 (x86_64-debian-linux-gnu)

有人可以解释为什么会发生这种情况吗?我真的很喜欢进程替换......

谢谢

编辑:如果 cat 要从 echo 中读取,则进程替换中的正确重定向是:

cat <( echo hello; )

答案1

你的代码cat >( echo hola; )永远不会退出,因为,

  • 它首先会回显该模式hola
  • 并接受输入进行写入。
  • 当我们给Ctrl+D它时,它会继续搜索要写入的文件。

选项1:将上下文写入回显的文件中

cat > $( echo hola; )

因此,无论我们在下面给出什么上下文,都将保存到名为hola.

注意:我们可以通过以下方式退出 cat 块Ctrl+D

选项2:捕捉回显的上下文。

cat <(echo hola;)

答案2

我不知道你想实现什么目标,但是:

  1. >(...)使正在运行的任何内容的标准输入都可用于写入
  2. cat需要一个可以读取的文件

不保证 (1) 提供的任何内容都可以读取。在 macOS 上,我刚刚收到一个错误:

bash-4.4$ cat >( echo foo)
foo
cat: /dev/fd/63: Permission denied

在 Linux 上,对我来说,它是一根管道,另一端什么也没有写:

$ strace -e openat cat >(echo foo)
foo
...
openat(AT_FDCWD, "/dev/fd/63", O_RDONLY) = 3

和:

$ ll /proc/$(pgrep cat)/fd/3
lr-x------ 1 muru muru 64 Aug 13 18:55 /proc/3381/fd/3 -> 'pipe:[37501]'
$ lsof | grep 37501
strace    3433                 muru   63w     FIFO               0,12      0t0      37501 pipe
cat       3435                 muru    3r     FIFO               0,12      0t0      37501 pipe
cat       3435                 muru   63w     FIFO               0,12      0t0      37501 pipe

另一端关闭标准输入并退出并不重要 - 它只打开了管道阅读,没有写入,并且没有任何内容写入管道。所以cat将留在那里,等待阅读完成。 (这里stracecat 这里都有一个打开的文件句柄用于写入该管道,但这是因为 bash 打开了它以进行写入并使其可供它们使用。两者都不会写入它。)

答案3

流程替代本身就是一个主题。需要认识到的重要一点是,它更像是 FIFO,而不是 stdin 或 stdout。你可以用 echo 看到这一点:

echo >( echo hello; )

给你:/dev/fd/63 你好

外部回声为您提供实际给出的参数,即/dev/fd/63。所以,你的

cat >( echo hello; )

实际上是cat /dev/fd/43,输出被发送到echo hello。(43 只是一个例子;这个数字是随机的,但通常是 63)

您还可以看到以下之间的区别:

echo hop > >(cat)

这给出了hop

echo hop  >(cat)

这使hop /dev/fd/63

另外,举个例子:

 sed 's/$/klap/' | tee >(sed 's/^/hop/')

给出输入klop

klopklap
hopklopklap

theklopklap是 的标准输出tee,是 进程中替换hopklopklap的标准输出。sed

那么为什么会cat >(echo hello)挂起呢?因为,如前所述, cat 得到一个参数/dev/fd/32,并且从该“文件”中它永远不会得到 EOF。

答案4

cat不会挂起,它正在等待您的输入。cat读取标准输入并写入标准输出。您不重定向标准输入,因此标准输入是您的终端。当您键入 时Ctrl+D,您表示文件结束,并且您的cat将终止。

相关内容