last day (15 days later) » 

01:22
-1
A: Why is the stdout of a `>()` subshell different if it's part of a redirection (e.g. `> >()`)?

Niko GambtIn command1 > >(command2), the scope of the redirection > is command1 only, i.e. it redirects the standard out of command1 to the file >(command2), and the same redirection does not redirect the standard out of command2 (and the same redirection also certainly does not redirect the standard out o...

JoL
JoL
Maybe I'm misunderstanding, but what you say seems to contradict the examples I've given. In command > >(command2), command2's output is redirected to the pipe and does not inherit the terminal output of the shell. This happens in both bash and zsh.
Just run cat /dev/null > >(readlink /proc/self/fd/1). I'm using Bash and it returns /dev/pts/0, which is a "tty", not a pipe.
JoL
JoL
Because you're not using a pipe in that example. Use cat /dev/null > >(readlink /proc/self/fd/1) | cat, and that returns something like pipe:[687354].
Your second paragraph says that command2 does not inherit the file descriptor 1 of command1 that has been redirected and instead inherits the file descriptor 1 of the shell. I'm practically quoting your second paragraph. In this last example with the pipe we can see that it does actually inherit that of the command and not of the shell. If it were of the shell, it'd stay as a terminal device and not the pipe.
Exactly. I'm not using a pipe. I'm just showing you that the stdout of command1 and command2 are different because the fd 1 of command1 has been redirected, whereas the fd 1 of command2 is inherited from the parent process, the shell. Hence, it answers the question that you put in the title.
JoL
JoL
Why do you say that command2 inherits from the shell? The shell's stdout is a terminal device, yet readlink /proc/self/fd/1 tells us that command2's stdout is a pipe. It also just so happens that command1's stdout is a pipe. So why do you say they are different?
01:22
cat /dev/null > >(readlink /proc/self/fd/1) does not return a pipe. Mine returns /dev/pts/0 as I said. The reason is because command2 is a child process of the shell. command2 is not a child process of command1, and the child process inherits all the open file descriptors of the parent process.
JoL
JoL
The problem with that example (not using | cat) is that you can't see the difference. command1 and the shell both have the same stdout, so how can you tell where command2's stdout was inherited from? The point of | cat is to make them different and allow us to differentiate them. You know what's interesting, is that before asking this question and the previous one, I also thought that these subshells inherited from the shell and not command1, but these example commands prove us wrong.
I'm trying to think of how to make this clear to you, but I'm running out of ideas.
No. When you do command1 > >(command2), you redirect the fd 1 of command1 to the file returned by the process substitution >(command2). So, command1 does not have the same stdout as the shell.
JoL
JoL
I've just noticed that extending this example to use | cat causes one to use zsh's MULTIOS redirection, which probably makes the concept more murky. What about this:
I can tell that command2 inherits fd 1 of the shell and, hence, command2 has the same stdout as the shell because the GNU Bash Manual says that command2 in the process substitution >(command2) is run in a sub-shell (a child process of the shell).
If you run readlink /proc/self/fd/1 by itself in your shell, you get the same tty device as running cat /dev/null > >(readlink /proc/self/fd/1).
JoL
JoL
Ok. Can you tell me why `true 2> >(readlink /proc/self/fd/1) | cat returns pipe:[714338], since the shell's stdout is a terminal device?
If readlink inherited from the shell, it should be a terminal device as you say, right?
01:39
The pipe redirects the fd 1 of readlink to the standard in of cat. It's just that.
JoL
JoL
Which is effectively inheriting the stdout of true.
I imagine that sets up the pipe to cat after forking for true but before exec'ing true, and before forking for readlink.
Well, I imagine the shell makes the pipe first, then forks three processes, and then dup2() the file descriptors.
JoL
JoL
dup2'ing them before forking the 3rd process for the readlink subshell.
It seems we've come to an agreement that command2 does inherit command1's stdout and not the shell's.
No, I absolutely do not agree that command2 is a child process of command1.
JoL
JoL
Maybe what's missing is coming to an agreement as to what command1 is. I'm taking it as everything after fork, including the shell's code before exec'ing the command.
01:51
I can't tell you the order of the dup2() and forking, cause I don't know the source code, but I don't think you know the source code either.
JoL
JoL
Haven't read it, but the point of this discussion is what makes sense with the observations we can make. command2's stdout is the same as command1
sorry... command1's and it's possible to do this via "inheritance" so can't we just accept it as so?
What I imagine in left-hand-side | right-hand-side, to put it simply is that all the fd 1's of all the processes on the left hand side are redirected to a pipe.
JoL
JoL
You mean a separate dup2() per process?
Guess what. Doing cat 2> >(cat -) | cat - - in one terminal and then pstree -spa on them shows that >(cat -) is actually a child process of the first cat.
Really? Interesting
What about without the pipe?
JoL
JoL
It's still a child.
02:01
cool
I'll delete my answer
JoL
JoL
If I do cat >(cat -) then it isn't.
Owh
very interesting
JoL
JoL
And that, my friend, is why I posted the question.
It is very interesting.
Well, then, you have your answer already with pstree
02:21
Just want to say that, pipe() always happens first before forking. Otherwise, if you fork() then pipe() in the child process, both ends of the pipe are connected to the same child process.

last day (15 days later) »