Shell: mutual piping of STDIN/STDOUT of two commands

When we run this with a POSIX shell,

$ cmd0 | cmd1

STDOUT of cmd0 is piped to STDIN of cmd1.

Q: On top of this, how can I also pipe STDOUT of cmd1 to STDIN of cmd0?

Is it mandatory to use redirect from/into a named pipe (FIFO) ? I don’t like named pipes very much because they occupy some filesystem paths and I need to worry about name collisions. Or do I have to call pipe(2) via C, Python or some general purpose programming languages?

(Both cmd0 and cmd1 do some network I/O, so they won’t block each other forever.)

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

On systems with bi-directional pipes (not Linux), you can do:

cmd0 <&1 | cmd1 >&0

On Linux, you can do:

: | { cmd1 | cmd2; } > /dev/fd/0

That works because on Linux (and Cygwin, but generally not other systems) /dev/fd/x where x is a fd to a pipe (named or not) acts like a named pipe, that is, opening it in read mode gets you the reading end and in write mode gets you the writing end.

With the yash shell and its x>>|y pipeline redirection operator:

{ cmd0 | cmd1; } >>|0

With shells with coproc support:

  • zsh:
       coproc cmd0
       cmd1 <&p >&p
  • ksh
       cmd0 |&
       cmd1 <&p >&p
  • bash4+
       coproc cmd0
       cmd1 <&"${COPROC[0]}" >&"${COPROC[1]}"

Dedicated tool approaches (shamelessly copied from answers on this very similar question):

Using pipexec

pipexec [ A /path/to/cmd0 ] 
        [ B /path/to/cmd1 ] 
        '{A:1>B:0}' '{A:0>B:1}'

Or using dpipe

dpipe cmd0 = cmd1

Or using socat:

socat EXEC:cmd0 EXEC:cmd1,nofork                 # using socketpairs
socat EXEC:cmd0,commtype=pipes EXEC:cmd1,nofork  # using pipes

I don’t know about python, but that’s also relatively easily done in perl:

perl -e 'pipe STDOUT,STDIN; exec "cmd0 | cmd1"'

You can always also resort to named pipes, but finding unique names for them and some safe directory to create them in, restricting access to them (so other processes can’t open them and interfere) and cleanup afterwards become additional problems which are hard to overcome reliably and portably.

In any case, beware of deadlocks!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x