В 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
Во всех трех оболочках процесс ps
находится в другой группе процессов, чем cat
, которая является группой процессов переднего плана терминала. zsh
, по крайней мере, достаточно хорош, чтобы перенаправить stdin в нем на /dev/null
, если это был tty, чтобы избежать проблем с этим, как многие оболочки делают для команд, выполняемых в фоне.
Ваша команда работала бы нормально, если бы stdin не был терминалом, но здесь, поскольку cat
не находится в группе процессов переднего плана терминала, его чтение из терминала означает, что он получит сигнал SIGTTIN
, который приведет к его приостановке. А это не обрабатывается изящно. В вашем случае, похоже, SIGTTIN
игнорируется или блокируется, чтобы вы получили ошибку EIO (которую вы получаете при попытке чтения с вашего управляющего терминала, когда вы не находитесь в его группе процессов переднего плана и игнорируете/блокируете SIGTTIN
).
В
(head <(cat <&3)) 3<&0
Однако, мы запускаем под-оболочку на переднем плане, и все процессы в ней оказываются в той же группе процессов, поэтому им разрешено чтение с терминала. С явным перенаправлением в zsh
мы обходим перенаправление zsh
с /dev/null
. В других оболочках также подойдет
(head <(cat))
-.