Why not just do:
{ echo foo; echo bar;} > /tmp/p
If you want your controlling script to leave the pipe open, you can do:
exec 3<> /tmp/p
Opening a named pipe in read-write mode is to avoid that to block if the pipe hasn't been opened yet. That would instantiate it if it wasn't yet. It works on Linux at least but is not guaranteed to by POSIX.
Alternatively (and portably):
: < /tmp/p & exec 3> /tmp/p
Then instead of having each process open the named pipe, you can also do:
cmd >&3
And in the end, you'd do:
exec 3>&-
To close the writing end to let readers know it's finished.
change all <
s to >
s and <
s to >
s if you need the logic to be the other way round.
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.
Best Answer
As stated by @MelBoyce in his comment, this is because of the conceptual nature of a pipe. It has a input and an output, and you read the bytes from the output in the exact same order they were written into the input. Pipes are not common files or pointers, you're not suppose to read and write anywhere in it. You're forced to read the first bytes that entered the pipe and that never be read yet.
Pipes may be implemented as a buffer in memory, but the implementation could vary if in the future, if another more efficient way to do it is invented for example. However, the conceptual nature of the pipe won't change. You'll still use the same
read(1)
andwrite(1)
system calls and they still behave the same. The file descriptors you get when you callpipe(1)
are used to force you to use the pipe correctly (and additionally provide some access control). That way, future modifications in the implementation won't break your code.