As for the cause, use strace
.
tail -f | strace bash >> foo
The second echo echo hello > pToB
gives me then this:
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "e", 1) = 1
read(0, "c", 1) = 1
read(0, "h", 1) = 1
read(0, "o", 1) = 1
read(0, " ", 1) = 1
read(0, "h", 1) = 1
read(0, "e", 1) = 1
read(0, "l", 1) = 1
read(0, "l", 1) = 1
read(0, "o", 1) = 1
read(0, "\n", 1) = 1
write(1, "hello\n", 6) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=3299, si_uid=1000} ---
+++ killed by SIGPIPE +++
So, the second time it tries to write hello\n, it gets a broken pipe error; that's why you can't read hello (it was never written), and bash quits so that's the end of it.
You'd have to use something that keeps the pipe open, I guess.
How about this?
(while read myline; do echo $myline; done) < pToP
For more background information, man 7 pipe
may be relevant, it describes the various error cases around pipes.
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.
Best Answer
No, it's
that hangs. More precisely, it's the shell opening the pipe for writing before running
echo
.pipe
are inter-process communication mechanisms, they are to be used between processes running concurrently. Here, theopen(WR_ONLY)
(>
) will block until another process does anopen
in read mode.will work because
echo
andcat
run concurrently.On Linux, you can get away with:
That works because read+write
open
s (<>
) on pipes don't block on Linux, and because thetest\n
output byecho
is small enough to fit in the pipe, so you can do the write and the read sequentially.It wouldn't work for a larger output like:
Because
seq
would fill up the pipe (64kiB in current versions of Linux) and block until some other process reads data off that pipe, which will never happen becausecat
won't run untilseq
has finished.Note that:
would not work either because the
echo
command line would open the pipe, write test and then close the pipe (and then the system would destroy it as there's no file descriptor open to it anymore). So the nextcat
command line would try to instantiate a new pipe (and block until something opens the fifo file for writing).