How can I keep a FIFO open for reading?

803 Views Asked by At

I'm trying to redirect a program's stdin and stdout. I'm currently experimenting with a bash mockup of this, but I'm getting some odd behavior.

I have the following:

mkfifo in
mkfifo out

I also have the following script, test.sh

#!/bin/bash

while read line; do
  echo "I read ${line}"
done < /dev/stdin

In terminal 1, I do the following:

tail -f out

In terminal 2, I do the following:

./test.sh < in > out

In terminal 3, I do the following:

echo "foo" > in
echo "bar > in

However, instead of seeing "I read foo" followed by "I read bar" in terminal 1, I get nothing after the first echo, both lines after the second echo, and then the test.sh program in terminal 2 exits. How can I prevent the exit so I can keep sending test.sh input? Also, instead of buffering and then dumping when the program terminates, how can I get the output from test.sh to flush to the tail -f in terminal 1?

1

There are 1 best solutions below

1
On BEST ANSWER

Use the redirection on a single compound command that contains your two echo commands.

{
  echo "foo"
  echo "bar"
} > in

If, as seems likely on a closer reading, you want in to stay open while you are executing commands interactively, use exec to open in on another file descriptor:

exec 3> in      # Open in on file descriptor 3
echo "foo" >&3  # Write to file descriptor 3 instead of standard output
echo "bar" >&3  # "
exec 3>&-       # Close file descriptor 3

Note that exec 3> in will block until something (test.sh in your case) opens in for reading, and due to buffering, you may not see any output from tail -f out until you close file descriptor 3.