communication between multiple processes
The term for what you're trying to accomplish is multiplexing.
This can be accomplished fairly easily in bash, but it does require some more advanced bash features.
I created a script based on your which I think does what you're trying to accomplish. I'll explain it below.
#!/bin/bash
manager() {
while IFS= read -r line; do
echo "manager[$1:$BASHPID]: $line"
done
}
fds=()
for (( i=0; i<5; i++ )); do
exec {fd}> >(manager $i)
fds+=( $fd )
done
while IFS= read -r line; do
echo "master: $line"
for fd in "${fds[@]}"; do
printf -- '%s\n' "$line" >&$fd
done
done
manager
is a bash function which simply reads from STDIN and writes it's identifier and the line to STDOUT. We use $BASHPID
instead of $$
as $$
does not get updated for subshells (which is what we will be using to launch manager
.
fds
is an array that will hold the file descriptors pointing to the STDIN pipes of the various manager
s spawned off.
Then we loop through and create 5 manager processes. I use the for (( ))
syntax instead of the way you were doing it as it's cleaner. This is bash specific, but several of the things this script does are bash specific, so might as well go all the way.
Next we get to exec {fd}> >(manager $i)
. This does several more bash specific things.
The first of which is {fd}>
. This grabs the next available file descriptor on or after number 10, opens a pipe with the writing side of the pipe assigned to that file descriptor, and assigns the file descriptor number to the variable $fd
.
The >(manager $i)
launches manager $i
and basically substitutes >(manager $i)
with a path to a STDIN of that process. So if manager
was launched as PID 1234, >(manager $i)
might get substituted with /proc/1234/fd/0
(this is OS dependent).
So assuming the next available file descriptor number is 10, and manager is launched with PID 1234, the command exec {fd}> >(manager $i)
basically becomes exec 10>/proc/1234/fd/0
, and bash now has file descriptor pointing to STDIN of that manager.
Then since bash puts that file descriptor number in $fd
, we add that descriptor to the array fds
for later usage.
The rest of it is pretty simple. The master reads a line from STDIN, iterates over all the file descriptors in $fds
, and sends the line to that file desciptor (printf ... >&$fd
).
The result looks like this:
$ /tmp/test.sh
hello
master: hello
manager[0:8876]: hello
manager[1:8877]: hello
manager[4:8880]: hello
manager[2:8878]: hello
manager[3:8879]: hello
world
master: world
manager[0:8876]: world
manager[1:8877]: world
manager[3:8879]: world
manager[2:8878]: world
manager[4:8880]: world
Where I typed hello
and world
.