| 1 | #!/usr/bin/env bash
|
| 2 | #
|
| 3 | # Demo of coprocesses
|
| 4 | #
|
| 5 | # Usage:
|
| 6 | # ./coproc.sh <function name>
|
| 7 | #
|
| 8 | # Reference:
|
| 9 | # http://unix.stackexchange.com/questions/86270/how-do-you-use-the-command-coproc-in-bash
|
| 10 | #
|
| 11 | # Good observations:
|
| 12 | #
|
| 13 | # "In short, pipes aren't good for interacting with commands. Co-processes can
|
| 14 | # only be used to interact with commands that don't buffer their output, or
|
| 15 | # commands which can be told not to buffer their output; for example, by using
|
| 16 | # stdbuf with some commands on recent GNU or FreeBSD systems.
|
| 17 | #
|
| 18 | # That's why expect or zpty use pseudo-terminals instead. expect is a tool
|
| 19 | # designed for interacting with commands, and it does it well."
|
| 20 |
|
| 21 | set -o nounset
|
| 22 | set -o pipefail
|
| 23 | set -o errexit
|
| 24 |
|
| 25 | proc-tree() {
|
| 26 | #sleep 1 &
|
| 27 | echo
|
| 28 | pstree --ascii --arguments -p $$
|
| 29 |
|
| 30 | # Same result
|
| 31 | #pstree --ascii --arguments $BASHPID
|
| 32 | }
|
| 33 |
|
| 34 | readonly THIS_DIR=$(dirname $0)
|
| 35 |
|
| 36 | read-write() {
|
| 37 | local read_fd=$1
|
| 38 | local write_fd=$2
|
| 39 |
|
| 40 | for i in $(seq 5); do
|
| 41 | echo abc $i XYZ >& $write_fd
|
| 42 | read var <& $read_fd
|
| 43 | echo $var
|
| 44 | sleep 0.1
|
| 45 | done
|
| 46 | }
|
| 47 |
|
| 48 | simple-demo() {
|
| 49 | # With this syntax, there's only a single coprocess
|
| 50 | coproc $THIS_DIR/coproc.py
|
| 51 |
|
| 52 | proc-tree
|
| 53 | echo "COPROC PID: $COPROC_PID"
|
| 54 |
|
| 55 | # In ksh or zsh, the pipes to and from the co-process are accessed with >&p
|
| 56 | # and <&p.
|
| 57 | # But in bash, the file descriptors of the pipe from the co-process and the
|
| 58 | # other pipe to the co-process are returned in the $COPROC array
|
| 59 | # (respectively ${COPROC[0]} and ${COPROC[1]}.
|
| 60 |
|
| 61 | argv ${COPROC[@]}
|
| 62 |
|
| 63 | read-write "${COPROC[@]}"
|
| 64 | }
|
| 65 |
|
| 66 | multi-demo() {
|
| 67 | proc-tree
|
| 68 |
|
| 69 | coproc upper {
|
| 70 | $THIS_DIR/coproc.py upper
|
| 71 | }
|
| 72 | echo "upper PID: $upper_PID"
|
| 73 |
|
| 74 | proc-tree
|
| 75 | read-write "${upper[@]}"
|
| 76 |
|
| 77 | # Close the write end to signal we'redone
|
| 78 | exec {upper[1]}>&-
|
| 79 |
|
| 80 | echo '---'
|
| 81 |
|
| 82 | proc-tree
|
| 83 |
|
| 84 | coproc lower {
|
| 85 | $THIS_DIR/coproc.py lower
|
| 86 | }
|
| 87 | echo "lower PID: $lower_PID"
|
| 88 |
|
| 89 | proc-tree
|
| 90 | read-write "${lower[@]}"
|
| 91 |
|
| 92 | exec {lower[1]}>&-
|
| 93 | }
|
| 94 |
|
| 95 | "$@"
|