Il termine per ciò che stai cercando di realizzare è il multiplexing .
Questo può essere realizzato abbastanza facilmente in bash, ma richiede alcune funzionalità bash più avanzate.
Ho creato uno script basato sul tuo, che penso faccia quello che stai cercando di realizzare. Lo spiego di seguito.
#!/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
è una funzione bash che legge semplicemente da STDIN e scrive il suo identificatore e la linea su STDOUT. Usiamo al $BASHPID
posto di $$
as $$
non viene aggiornato per i subshells (che è quello che useremo per il lancio manager
.
fds
è un array che conterrà i descrittori di file che puntano alle pipe STDIN delle varie manager
s generate.
Quindi eseguiamo il loop e creiamo 5 processi manageriali. Uso la for (( ))
sintassi invece del modo in cui la stavi facendo perché è più pulita. Questo è specifico per Bash, ma molte delle cose che questo script fa sono specifiche per Bash, quindi potrebbe anche andare fino in fondo.
Quindi arriviamo a exec {fd}> >(manager $i)
. Questo fa molte altre cose specifiche.
Il primo dei quali è {fd}>
. Questo prende il successivo descrittore di file disponibile sul o dopo il numero 10, apre una pipe con il lato di scrittura della pipe assegnato a quel descrittore di file e assegna il numero del descrittore di file alla variabile $fd
.
Il >(manager $i)
lancio manager $i
e sostanzialmente sostituisce >(manager $i)
con un percorso a un STDIN di quel processo. Quindi, se è manager
stato lanciato come PID 1234, >(manager $i)
potrebbe essere sostituito con /proc/1234/fd/0
(dipende dal sistema operativo).
Quindi, supponendo che il prossimo numero del descrittore di file disponibile sia 10 e che il gestore venga avviato con PID 1234, il comando exec {fd}> >(manager $i)
sostanzialmente diventa exec 10>/proc/1234/fd/0
, e bash ora ha il descrittore di file che punta a STDIN di quel gestore.
Quindi, poiché bash inserisce il numero del descrittore di file $fd
, aggiungiamo tale descrittore all'array fds
per un uso successivo.
Il resto è piuttosto semplice. Il master legge una riga da STDIN, scorre su tutti i descrittori di file in $fds
e invia la riga a quel file desciptor ( printf ... >&$fd
).
Il risultato è simile al seguente:
$ /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
Dove ho scritto hello
e world
.