In bash
, if you do:
$ 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
In 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
In 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
In all 3 shells, the ps
process is in a different process group from cat
's one, which is the foreground process group of the terminal. zsh
at least is nice enough to redirect stdin in there to /dev/null
if it was a tty to avoid problems with that, like many shells do for commands run in background.
Your command would work OK if stdin was not a terminal, but here, since cat
is not in the foreground process group of the terminal, it reading from the terminal means it will receive a SIGTTIN
signal which would cause it to be suspended. And that is not handled gracefully here. In your case, it seems SIGTTIN
is being ignored or blocked for you to get a EIO error (which you get when trying to read from your controlling terminal when you're not in its foreground process group and ignore/block SIGTTIN
).
In
(head <(cat <&3)) 3<&0
however, we're starting a sub-shell in foreground, and all the processes in there end up in that same process group so are allowed to read from the terminal. With the explicit redirection in there, with zsh
, we're bypassing zsh
's redirection from /dev/null
. With other shells,
(head <(cat))
would also work.