Skip to main content
Added reader-writer
Source Link
Chris Davies
  • 128.4k
  • 16
  • 179
  • 324
First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read   First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh both /etc/passwd 
#!/bin/bash # pipe=/tmp/mypipe ######################################################################## # Reader # doRead() { echo "Reading from pipe $pipe" >&2 nl <"$pipe" } ######################################################################## # Writer. We pause after every line (for effect) # doWrite() { [[ $# -eq 0 ]] && set -- - echo "Writing to pipe $pipe" >&2 cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe" } ######################################################################## # Reader-Writer. We pause after every line (for effect) # doBoth() { [[ $# -eq 0 ]] && set -- - echo "Reading and writing to pipe $pipe" >&2 exec 3<>"$pipe" nl <&3 & readPID=$!  cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >&3 kill $readPID 2>/dev/null } ######################################################################## # action="$1" shift if [[ ! -p "$pipe" ]] then echo "Creating pipe $pipe" >&2 mkfifo "$pipe" fi case "$action" in read*) doRead "$@" ;; write*) doWrite "$@" ;; both) doBoth "$@" ;; esac 
First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read 
#!/bin/bash # pipe=/tmp/mypipe ######################################################################## # Reader # doRead() { echo "Reading from pipe $pipe" >&2 nl <"$pipe" } ######################################################################## # Writer. We pause after every line (for effect) # doWrite() { [[ $# -eq 0 ]] && set -- - echo "Writing to pipe $pipe" >&2 cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe" } ######################################################################## # action="$1" shift if [[ ! -p "$pipe" ]] then echo "Creating pipe $pipe" >&2 mkfifo "$pipe" fi case "$action" in read*) doRead "$@" ;; write*) doWrite "$@" ;; esac 
First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read   First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh both /etc/passwd 
#!/bin/bash # pipe=/tmp/mypipe ######################################################################## # Reader # doRead() { echo "Reading from pipe $pipe" >&2 nl <"$pipe" } ######################################################################## # Writer. We pause after every line (for effect) # doWrite() { [[ $# -eq 0 ]] && set -- - echo "Writing to pipe $pipe" >&2 cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe" } ######################################################################## # Reader-Writer. We pause after every line (for effect) # doBoth() { [[ $# -eq 0 ]] && set -- - echo "Reading and writing to pipe $pipe" >&2 exec 3<>"$pipe" nl <&3 & readPID=$!  cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >&3 kill $readPID 2>/dev/null } ######################################################################## # action="$1" shift if [[ ! -p "$pipe" ]] then echo "Creating pipe $pipe" >&2 mkfifo "$pipe" fi case "$action" in read*) doRead "$@" ;; write*) doWrite "$@" ;; both) doBoth "$@" ;; esac 
Source Link
Chris Davies
  • 128.4k
  • 16
  • 179
  • 324

On (at least) Linux-based systems a FIFO or Named Pipe is unidirectional. In your situation you want to have a program reading and writing to the same FIFO. This gets even more tricky because you may well up with a deadlock if you exceed the pipe's internal buffer.

Two general points.

  1. You cannot usefully have two readers; if you do, you'll find that your reads will interleave nondeterministically and your data will be shared between the two readers. You will not get the same data duplicated to both readers.

  2. You can have two (or more) writers, but once again your output data will be interleaved in the order that it is received by the pipe. Unless your writers are carefully synchronised, data such as First writer and Second writer could end up being received as the garbled FirSecond wrstwrititerer.

Using the program at the bottom of this answer, consider running the following two scenarios from different terminal sessions. Then try your own variations.

First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts First terminal Second terminal Third terminal -------------------- -------------------- -------------------- ./fifo.sh write /etc/passwd ps -ef | ./fifo.sh write ./fifo.sh read 

Script for fifo.sh as follows

#!/bin/bash # pipe=/tmp/mypipe ######################################################################## # Reader # doRead() { echo "Reading from pipe $pipe" >&2 nl <"$pipe" } ######################################################################## # Writer. We pause after every line (for effect) # doWrite() { [[ $# -eq 0 ]] && set -- - echo "Writing to pipe $pipe" >&2 cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe" } ######################################################################## # action="$1" shift if [[ ! -p "$pipe" ]] then echo "Creating pipe $pipe" >&2 mkfifo "$pipe" fi case "$action" in read*) doRead "$@" ;; write*) doWrite "$@" ;; esac