El término para lo que estás tratando de lograr es multiplexación .
Esto se puede lograr con bastante facilidad en bash, pero requiere algunas características de bash más avanzadas.
Creé un script basado en tu que creo que hace lo que intentas lograr. Lo explicaré a continuación.
#!/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
es una función bash que simplemente lee desde STDIN y escribe su identificador y la línea en STDOUT. Usamos en $BASHPID
lugar de $$
como $$
no se actualiza para subcapas (que es lo que usaremos para iniciar manager
.
fds
es una matriz que contendrá los descriptores de archivo que apuntan a las tuberías STDIN de los diversos manager
s generados.
Luego recorremos y creamos 5 procesos de administrador. Utilizo la for (( ))
sintaxis en lugar de la forma en que lo hacía, ya que es más limpia. Esto es específico de bash, pero varias de las cosas que hace este script son específicas de bash, por lo que bien podría ir hasta el final.
A continuación llegamos a exec {fd}> >(manager $i)
. Esto hace varias cosas más específicas de bash.
El primero de los cuales es {fd}>
. Esto toma el siguiente descriptor de archivo disponible en o después del número 10, abre una tubería con el lado de escritura de la tubería asignado a ese descriptor de archivo y asigna el número de descriptor de archivo a la variable $fd
.
Se >(manager $i)
inicia manager $i
y básicamente se sustituye >(manager $i)
con una ruta a un STDIN de ese proceso. Entonces, si manager
se lanzó como PID 1234, >(manager $i)
podría ser sustituido por /proc/1234/fd/0
(esto depende del sistema operativo).
Entonces, suponiendo que el siguiente número de descriptor de archivo disponible sea 10, y el administrador se inicie con PID 1234, el comando exec {fd}> >(manager $i)
básicamente se convierte exec 10>/proc/1234/fd/0
, y bash ahora tiene un descriptor de archivo que apunta a STDIN de ese administrador.
Luego, como bash pone ese número de descriptor de archivo $fd
, agregamos ese descriptor a la matriz fds
para su uso posterior.
El resto es bastante simple. El maestro lee una línea de STDIN, itera sobre todos los descriptores de archivo $fds
y envía la línea a ese descriptor de archivo ( printf ... >&$fd
).
El resultado se ve así:
$ /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
Donde escribí hello
y world
.