1173
Comment: link to NamedPipes
|
← Revision 22 as of 2016-10-17 20:45:47 ⇥
3277
remove useless quotes of constants, quote variable expansion. remove useless :
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
[[Anchor(faq85)]] | <<Anchor(faq85)>> |
Line 3: | Line 3: |
In the general case, you'll open a new FileDescriptor (FD) pointing to the fifo, and write through that. For simple cases, it may be possible to skip that step. | |
Line 4: | Line 5: |
The basic use of NamedPipes is: | === The problem === The most basic use of NamedPipes is: |
Line 7: | Line 11: |
cat < myfifo & echo 'a' > myfifo |
cat <myfifo & echo a >myfifo }}} This works, but `cat` dies after reading one line. (In fact, what happens is when the named pipe is closed by all the ''writers'', this signals an end of file condition for the ''reader''. So `cat`, the reader, terminates because it saw the end of its input.) What if we want to write several times to the pipe without having to restart the reader? === Grouping the commands === We have to arrange for all our data to be sent without opening and closing the pipe multiple times. If the commands are consecutive, they can be grouped: {{{ cat <myfifo & { echo a; echo b; echo c; } >myfifo |
Line 11: | Line 28: |
This works, but `cat` dies after reading one line. (In fact, what happens is each time the named pipe is closed by the ''writer'', this signals an end of file condition for the ''reader''. So `cat`, the reader, terminates because it saw the end of its input.) | |
Line 13: | Line 29: |
What if we want to write several times to the pipe without having to restart the reader? We have to arrange for all our data to be sent without opening and closing the pipe multiple times. | === Opening a file descriptor === |
Line 15: | Line 31: |
If the commands are consecutive, they can be grouped: | It is basically the same idea as above, but using exec to have greater flexibility: |
Line 17: | Line 34: |
cat < myfifo & { echo 'a'; echo 'b'; echo 'c'; } > myfifo }}} But if they can't be grouped for some reason, a better way is to assign a file descriptor to the pipe and write there: {{{ cat < myfifo & |
cat <myfifo & |
Line 29: | Line 40: |
echo 'a' >&3 echo 'b' >&3 echo 'c' >&3 |
echo a >&3 echo b >&3 echo c >&3 |
Line 36: | Line 47: |
Closing the FD causes the pipe's reader to receive the end of file indication. | |
Line 37: | Line 49: |
Closing the fd causes the pipe's reader to receive the end of file indication. | This works well as long as all the writers are children of the same shell. === Using tail === The use of `tail -f` instead of `cat` can be an option, as tail will keep reading even if the pipe is closed: {{{ tail -f myfifo & echo a >myfifo # Doesn't die echo b >myfifo echo c >myfifo }}} The problem here is that the process `tail` doesn't die, even if the named pipe is deleted. In a script this is not a problem as you can kill `tail` on exit. If your reader is a program that only reads from a file, you can still use tail with the help of process substitution: {{{ myprogram <(tail -f myfifo) & # Doesn't die echo b >myfifo echo c >myfifo }}} Here, tail will be closed when myprogram exits. === Using a guarding process === The reader of the pipe won't receive an EOF until ''all'' open writer file descriptors are closed. You can exploit this by keeping a file descriptor opened on a process doing nothing. Therefore, an elegant solution is to create a "guarding process", and to use a second pipe to control the guarding process: {{{ mkfifo myfifo mkfifo guard # keep the fifo opened using a fake writer >myfifo <guard & #note the order is important! # if you do <guard first, it will be blocked # and >myfifo will not be opened until guard is opened # start the reader cat myfifo }}} Now you can use writers in other unrelated processes, and the pipe will not be closed because of your process keeping it opened. {{{ echo something >myfifo # reader does not die }}} When you are finished and want to close the pipe, you just need to open and close the helper pipe to unblock the guarding processs: {{{ >guard }}} An alternative is to use a process doing nothing, killing it in the end: {{{ mkfifo myfifo while :;do sleep 10000 & wait;done >myfifo & pid=$! cat myfifo kill "$pid" }}} |
How to write several times to a fifo without having to reopen it?
In the general case, you'll open a new FileDescriptor (FD) pointing to the fifo, and write through that. For simple cases, it may be possible to skip that step.
The problem
The most basic use of NamedPipes is:
mkfifo myfifo cat <myfifo & echo a >myfifo
This works, but cat dies after reading one line. (In fact, what happens is when the named pipe is closed by all the writers, this signals an end of file condition for the reader. So cat, the reader, terminates because it saw the end of its input.)
What if we want to write several times to the pipe without having to restart the reader?
Grouping the commands
We have to arrange for all our data to be sent without opening and closing the pipe multiple times.
If the commands are consecutive, they can be grouped:
cat <myfifo & { echo a; echo b; echo c; } >myfifo
Opening a file descriptor
It is basically the same idea as above, but using exec to have greater flexibility:
cat <myfifo & # assigning fd 3 to the pipe exec 3>myfifo # writing to fd 3 instead of reopening the pipe echo a >&3 echo b >&3 echo c >&3 # closing the fd exec 3>&-
Closing the FD causes the pipe's reader to receive the end of file indication.
This works well as long as all the writers are children of the same shell.
Using tail
The use of tail -f instead of cat can be an option, as tail will keep reading even if the pipe is closed:
tail -f myfifo & echo a >myfifo # Doesn't die echo b >myfifo echo c >myfifo
The problem here is that the process tail doesn't die, even if the named pipe is deleted. In a script this is not a problem as you can kill tail on exit.
If your reader is a program that only reads from a file, you can still use tail with the help of process substitution:
myprogram <(tail -f myfifo) & # Doesn't die echo b >myfifo echo c >myfifo
Here, tail will be closed when myprogram exits.
Using a guarding process
The reader of the pipe won't receive an EOF until all open writer file descriptors are closed. You can exploit this by keeping a file descriptor opened on a process doing nothing.
Therefore, an elegant solution is to create a "guarding process", and to use a second pipe to control the guarding process:
mkfifo myfifo mkfifo guard # keep the fifo opened using a fake writer >myfifo <guard & #note the order is important! # if you do <guard first, it will be blocked # and >myfifo will not be opened until guard is opened # start the reader cat myfifo
Now you can use writers in other unrelated processes, and the pipe will not be closed because of your process keeping it opened.
echo something >myfifo # reader does not die
When you are finished and want to close the pipe, you just need to open and close the helper pipe to unblock the guarding processs:
>guard
An alternative is to use a process doing nothing, killing it in the end:
mkfifo myfifo while :;do sleep 10000 & wait;done >myfifo & pid=$! cat myfifo kill "$pid"