10

I have two processes that interface with one another over stdin and stdout.

Suppose I have process A and process B. The stdout of B needs to feed into the stdin of A, and the stdout of A needs to feed in to that of process B.

Is there a simple way to express this relationship in a simple command, or is there a basic shell script that can enable this?

Thanks in advance.

Bill
  • 2,319
  • 9
  • 29
  • 36

3 Answers3

6

Bash 4 introduces coproc:

declare -a FDS
coproc FDS { process_A; }
process_B <&${FDS[0]} >&${FDS[1]}
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 2
    Just when I thought I understood all the funny fd manipulations you can do with bash... +1. – je4d Mar 14 '12 at 22:16
  • Could you elaborate on that? The examples in the docs aren't straightforward. I think we could benefit from having a simple example here, with information where is each I/O connected. Are stdin and stdout connected both ways, mirrored? – user Mar 17 '22 at 17:30
2

Take a look at named pipes. Create one pipe for A to B, and one pipe for B to A. Then start A with its stdout redirected to the first, and its stdin redirected to the second. Then start B with the opposite.

It would look something like this:

mkfifo --mode=0666 /tmp/AtoB
mkfifo --mode=0666 /tmp/BtoA
A < BtoA > AtoB
B < AtoB > BtoA

add: Of course, they'll need some way to recognize that both parties are present. Something like a simple "I am here, are you?" that both receive a response to.

Important: As noted in comments below, this process will deadlock with both programs blocking on reads. Some form of coordination will be necessary to ensure this doesn't happen.

  • Thanks. I suppose each fifo is trivially small, right? Such that if the script does not remove them, it won't be a problem. Also, if a pipe with that name already exists, will it just overwrite it? – Bill Mar 13 '12 at 18:07
  • 1
    They aren't actually files on disk, just special files in the filesystem. They take up 0 bytes. Regarding overwriting, man mkfifo says that it'll return with an error EEXIST –  Mar 13 '12 at 18:10
  • Ok, so in my script I'll just make sure I do an rm -f on each fifo name before creating them. – Bill Mar 13 '12 at 18:13
  • This will probably deadlock since the processes will be waiting for each other's input only and their reads will block, so they don't get any chance to produce the output needed by the other side. – Michał Kosmulski Mar 13 '12 at 18:13
  • This will almost certainly deadlock, and command B will never even be executed. The shell will attempt to start A and will block until each fifo has a process attached to the other side. At the very least, the first command must be run in the background. – William Pursell Mar 13 '12 at 18:21
  • According to `man mkfifo`, "However, it has to be open at both ends simultaneously before you can proceed to do any input or output operations on it. Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa." –  Mar 13 '12 at 18:22
  • My plan would simply to be add an & following the line starting proc A – Bill Mar 13 '12 at 18:24
  • @Keith Whether a solution is possible depends on the apps' communication plan. If you just want both apps to depend on each other's input, there's a deadlock by definition. Someone has to go first and e.g. write something before he tries to read. But I don't have a good idea how to solve this even if we has this information. – Michał Kosmulski Mar 13 '12 at 18:25
0

(I would comment on Keith's answer, but don't have enough rep yet.)

Testing this on OpenBSD, I found it impossible to start the scripts by running:

./a < btoa > atob &
./b < atob > btoa

(atob and btoa being FIFOs, and the scripts a and b duplicating stdin)

However, after also backgrounding the second one, as soon as I ran > btoa in my shell (the null command, however opening btoa for writing), they started. (Beware the infinite loop!) I guess this means you need a third process.

I'm not sure if the behavior of FIFOs in such cases (e.g. multiple processes opening for writing) is standardized.

TaylanKammer
  • 5,177
  • 1
  • 19
  • 16