Shell – Prevent automatic EOFs to a named pipe, and send an EOF when I want it

fifoshell-scripttext processing

I have a program that exits automatically upon reading an EOF in a given stream ( in the following case, stdin ).
Now I want to make a shell script, which creates a named pipe and connect the program's stdin to it. Then the script writes to the pipe several times using echo and cat ( and other tools that automatically generates an EOF when they exit ). The problem I'm facing is, when the first echo is done, it sends an EOF to the pipe and make the program exit. If I use something like tail -f then I can't send an EOF when I intend to quit the program. I'm researching a balanced solution but to no avail.
I've already found both how to prevent EOFs and how to manually send an EOF but I can't combine them. Is there any hint?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

Best Answer

As others have indicated, the reader of a pipe receives EOF once there are no writers left. So the solution is to make sure there is always one writer holding it open. That writer doesn't have to send anything, just hold it open.

Since you're using a shell script, the simplest solution is to tell the shell to open the pipe for writing. And then close it when you're done.

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

Note that if you omit the last line, file descriptor 3 will be automatically closed (and thus the reader receive EOF) when the script exits. Aside from convenience, this also provides a safety of sorts if the script were to somehow terminate early.

Related Question