I think it is possible if you attach the process of the related interpreter to gdb. I tried it with this perl one-liner
perl -e 'do { print "x\n"; sleep(1) } while(1)'
and it works but unfortunately not with a similar bash script.
First of all you have to figure out the PID of that process whose output you want to capture. Then start gdb
in another terminal and execute the following gdb-commands
attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID
after that the whole data that is written to stderr
is redirected to /abs/olu/te/path/filename
, since
attach PID
attaches the process to gdb and stops it
call close(2)
closes the stderr
filedescriptor of the process (for stdout
the filedescriptor is 1)
call open(...)
opens a new file and takes the lowest unused integer for the newly created filedescriptor and
detach PID
continues the process
At least on my machine. The first two lines are POSIX compatible but not the third one.
The second and the third argument of open
in the third line are documented in man 2 open
. In my case 65 means that open
should create the file and open the file write-only i.e. O_WRONLY | O_CREAT
(defined in fcntl.h
). The third argument tells open to create the file with read and write permission for the user i.e. S_IWUSR | S_IRUSR
(defined in sys/stat.h
). So maybe you have to find out appropriate values on your machine by yourself.
The idiom >(...)
just means (in layman terms): "the name of a file".
And it works as a "name of a file" (sort of, all will be clear in an instant):
$ echo <(date)
/proc/self/fd/11
Or some other number/name on your OS. But echo does print a name, exactly as if you do:
$ echo ProcSubs11
ProcSubs11
And if a file with the label ProcSubs11 exists, you could also do:
$ cat ProcSubs11
contents_of_file_ProcSubs11
Which you could do exactly the same with:
$ cat <(date)
Fri Jan 15 21:25:18 UTC 2016
The difference is that the actual name of the "Process Substitution" is "not visible" and that the details are a lot longer than reading a simple file, as described quite well in all the painful detail in the link to How process substitution is implemented in bash?.
Having said the above, lets review your items.
Q 1
...seems operationally no different from a simple unnamed pipe...
Well, "Process Substitution" is exactly based in an unnamed pipe
as your given first link states:
- The bash process creates an unnamed pipe for communication between the two processes created later.
The difference is that all the ~6 steps explained in the link are simplified to one idiom >(...)
for writing to and <(...)
for reading from.
And, it could be argued that the connection (pipe) has a name, as a file has. Just that that name is hidden from the user (the /proc/self/fd/11
shown at the start).
Example 1
1) I add a pipe and redirection of shasum's output ...
$ cat file_{1,2,3} | tee file_4 | shasum -a 256 > file_4.sha256
There is no "Process Substitution" there, but it worth noting (for later) that tee
sends (writes to) what it receive in its stdin
to a file file_4
and also sends the same stdin
content to stdout
. Which happens to be connected to a pipe (in this case) that writes to shasum.
So, in short, in layman terms, tee copy stdin
to both file_4
and shasum
.
Example 2
2) I try the same with ProcSub:
$ cat file_{1,2,3} | tee file_4 >(shasum -a 256 > file_4.sha256)
Re-using the description above (in layman terms) to describe this example:
Tee copy stdin
to three elements: file_4
, shasum
and stdout
.
Why?. Remember that >(...)
is the name of a file, lets put that in the line:
$ cat file_{1,2,3} | tee file_4 /proc/self/fd/11
tee is serving the input to two files file_4
and shasum
(via "Process Substitution") and the stdout
of tee
is still connected to its default place: the console. That is why you see the numbers in the console.
To make this example exactly equal to 1), we could do:
$ cat file_{1,2,3} | tee file_4 > /proc/self/fd/11 ### note the added `>`
Which becomes (yes, the space between >
and >(
must be used.
$ cat file_{1,2,3} | tee file_4 > >(shasum -a 256 > file_4.sha256)
That is redirecting tee
's stdout to the "Process Substitution".
Q 3
Q: So the general question is: how are i/o processed for the 3 cases above
I believe I just did explain the 3 cases, if not clear, please comment.
Q 4 (in comments, Please edit and add the question)
why the <(...) construct won't work in the third case.
Because (in layman terms) you can not insert a male prong into a male socket.
The <(...) idiom reads from what is inside the "Process substitution" and therefore provides an "output" and should be inserted in the stdin
of the outside command. The outside command tee
is trying to connect stdout
(like) elements. So, that pair could not match.
An important note:
The command cat
hides some details when applied to "Process Substitution", as both this command will give the same output:
$ cat <(date)
$ cat < <(date)
All is correct, but drawing conclusions from a misleading equality is wrong.
Best Answer
You can do it using reredirect (https://github.com/jerome-pouiller/reredirect/).
You can restore initial output of your process later using something like:
(
<M>
and<N>
are provided by previous launch of reredirect).reredirect
README
also explains how to redirect to another command or to redirect only stdout or stderr.