进程替换和 cat:无法读取标准输入

进程替换和 cat:无法读取标准输入

进程替换<(cat)不起作用。为什么?

head <(cat) 
cat: -: Input/output error

我可以使用额外的文件描述符,但我不明白为什么上面的方法不起作用。

# Using file descriptor 3 to reroute the input
(head <(cat <&3)) 3<&0

答案1

在 中bash,如果您这样做:

$ cat <(ps -j)
  PID  PGID   SID TTY          TIME CMD
 3887 16480 16480 pts/29   00:00:00 bash
 3888  3888 16480 pts/29   00:00:00 cat
 3889 16480 16480 pts/29   00:00:00 ps
16480 16480 16480 pts/29   00:00:00 bash

zsh

$ cat <(ps -j)
  PID  PGID   SID TTY          TIME CMD
 3935  3935 16480 pts/29   00:00:00 ps
 3936  3936 16480 pts/29   00:00:00 cat
16480 16480 16480 pts/29   00:00:00 zsh

ksh93

$ cat <(ps -j)
  PID  PGID   SID TTY          TIME CMD
 3946 16480 16480 pts/29   00:00:00 ps
 3947  3947 16480 pts/29   00:00:00 cat
16480 16480 16480 pts/29   00:00:00 ksh

在所有 3 个 shell 中,ps进程都位于与cat终端的前台进程组不同的进程组中。zsh至少可以将 stdin 重定向到/dev/nulltty 以避免出现问题,就像许多 shell 对在后台运行的命令所做的那样。

如果 stdin 不是终端,则您的命令可以正常工作,但在这里,由于cat不在终端的前台进程组中,因此它从终端读取意味着它将收到一个SIGTTIN信号,这将导致它被挂起。这里处理得并不优雅。在您的情况下,它似乎SIGTTIN被忽略或阻止,导致您收到 EIO 错误(当您不在其前台进程组并忽略/阻止时尝试从控制终端读取时,您会收到该错误SIGTTIN)。

(head <(cat <&3)) 3<&0

但是,我们在前台启动一个子 shell,其中的所有进程最终都位于同一进程组中,因此允许从终端读取。通过其中的显式重定向,zsh我们绕过了zsh来自 的重定向/dev/null。与其他贝壳一起,

(head <(cat))

也会起作用。

相关内容