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.