How to prevent terminating command to send EOF to named pipes?

The problem I faced is exactly this one: http://www.linuxmisc.com/4-linux/d7863c256bccbfb6.htm

I want to be able to run a program which takes stdin, and write data to it whenever I feel like it. I can do this with fifo named pipes. e.g.:

txtplay < named_pipe.fifo

echo "Hello World" > named_pipe.fifo

However, this has the disadvantage of the first command exiting after the second has finished. What I want is the same as:

txtplay

in effect, so I can just stick in my data whenever I like, and not worry about it seeing end-of-file. Unfortunately, I cannot simply do this, as I want the data to be sent to it to be processed through a filter before the program sees it.

Why don't I just load the program each time I want to send data to it? Too slow.

What I want, basically, is a way of redirecting the output of a given command to a fifo named pipe, without the end-of-file. While I'm at it, how does this EOF business work? Is there a special "EOF" command, or is it when no more data is received, or when the original program outputting the data exits?

Is there any solution to that?


Solution 1:

Run all your commands in a sub-shell (or in bash, within parenthesis), and redirect the subshell to the named pipe.

( 
     # some stuff
     echo "foo"
     # some other stuff
     echo "bar"
     # end of my commands
) > /home/foo/bar/named_pipe

And to answer the EOF question, EOF is written when the file handle closes. If you redirect from a program, you get EOF when that program (echo, in this case) terminates. By encapsulating multiple commands in parenthesis, you only get one EOF when the close parenthesis is reached.

Solution 2:

If you keep a handle open to the pipe, then it won't be closed by each echo command.

#!/usr/bin/env bash
fifo_with_exec() {
    echo "fifo_with_exec"

    readonly TMP_PIPE=$(mktemp -u)
    mkfifo -m 600 ${TMP_PIPE}
    echo "pipe created:  ${TMP_PIPE}"

    # Here is the important bit
    exec 9<> ${TMP_PIPE}

    zenity --progress --no-cancel < ${TMP_PIPE} &
    zenity_pid=$!
    echo "zenity_pid: ${zenity_pid}"

    echo "0" > ${TMP_PIPE}
    echo "#Run command A" > ${TMP_PIPE}
    echo "output of command A"
    sleep 2
    echo "40"  > ${TMP_PIPE}

    echo "#Run command B" > ${TMP_PIPE}
    echo "output of command B"
    sleep 2
    echo "80" > ${TMP_PIPE}

    echo "#Run command C" > ${TMP_PIPE}
    echo "output of command C"
    sleep 0.5
    echo "100" > ${TMP_PIPE}
}
fifo_with_exec

If you remove that exec statement you will notice that the function hangs on the second echo, as Zenity stops when it sees EOF from the first echo.