How to make bidirectional pipe between two programs?
Well, its fairly "easy" with named pipes (mkfifo
). I put easy in quotes because unless the programs are designed for this, deadlock is likely.
mkfifo fifo0 fifo1
( prog1 > fifo0 < fifo1 ) &
( prog2 > fifo1 < fifo0 ) &
( exec 30<fifo0 31<fifo1 ) # write can't open until there is a reader
# and vice versa if we did it the other way
Now, there is normally buffering involved in writing stdout. So, for example, if both programs were:
#!/usr/bin/perl
use 5.010;
say 1;
print while (<>);
you'd expect a infinite loop. But instead, both would deadlock; you would need to add $| = 1
(or equivalent) to turn off output buffering. The deadlock is caused because both programs are waiting for something on stdin, but they're not seeing it because its sitting in the stdout buffer of the other program, and hasn't yet been written to the pipe.
Update: incorporating suggestions from Stéphane Charzelas and Joost:
mkfifo fifo0 fifo1
prog1 > fifo0 < fifo1 &
prog2 < fifo0 > fifo1
does the same, is shorter, and more portable.
If pipes on your system are bidirectional (as they are on Solaris 11 and some BSDs at least, but not Linux):
cmd1 <&1 | cmd2 >&0
Beware of deadlocks though.
Also note that some versions of ksh93 on some systems implement pipes (|
) using a socket pair. socket pairs are bidirectional, but ksh93 explicitly shuts down the reverse direction, so the command above wouldn't work with those ksh93s even on systems where pipes (as created by the pipe(2)
system call) are bidirectional.
I am not sure if this is what you are trying to do:
nc -l -p 8096 -c second &
nc -c first 127.0.0.1 8096 &
This begins by opening a listening socket on port 8096, and once a connection is established, spawns program second
with its stdin
as the stream output and stdout
as the stream input.
Then, a second nc
is launched which connects to the listening port and spawns program first
with its stdout
as the stream input and its stdin
as the stream output.
This is not exactly done using a pipe, but it seems to do what you need.
As this uses the network, this can be done on 2 remote computers. This is almost the way a web server (second
) and a web browser (first
) work.