O termo para o que você está tentando realizar é multiplexing .
Isso pode ser feito com bastante facilidade no bash, mas requer alguns recursos bash mais avançados.
Eu criei um script baseado no seu que, na minha opinião, faz o que você está tentando realizar. Eu vou explicar isso abaixo.
#!/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
é uma função bash que simplesmente lê a partir de STDIN e grava seu identificador e a linha para STDOUT. Usamos $BASHPID
em vez de $$
, pois $$
não é atualizado para subshells (que é o que estaremos usando para lançar manager
.
fds
é uma matriz que conterá os descritores de arquivo que apontam para os canais STDIN dos vários manager
s gerados.
Então, percorremos e criamos 5 processos gerenciais. Eu uso a sintaxe for (( ))
em vez da maneira como você estava fazendo isso como é mais limpo. Isto é bash específico, mas várias das coisas que este script faz são específicas, assim como pode ir até o fim.
Em seguida, chegamos a exec {fd}> >(manager $i)
. Isso faz várias outras coisas específicas bash.
A primeira delas é {fd}>
. Isso pega o próximo descritor de arquivo disponível em ou após o número 10, abre um canal com o lado de escrita do canal atribuído a esse descritor de arquivo e atribui o número do descritor de arquivo à variável $fd
.
O >(manager $i)
lança manager $i
e basicamente substitui >(manager $i)
por um caminho para um STDIN desse processo. Portanto, se manager
foi lançado como PID 1234, >(manager $i)
pode ser substituído por /proc/1234/fd/0
(isso depende do sistema operacional).
Portanto, supondo que o próximo número de descritor de arquivo disponível seja 10 e o gerenciador seja iniciado com PID 1234, o comando exec {fd}> >(manager $i)
basicamente se tornará exec 10>/proc/1234/fd/0
e bash agora tem descritor de arquivo apontando para STDIN desse gerenciador.
Então, como o bash coloca esse número do descritor de arquivo em $fd
, adicionamos esse descritor à matriz fds
para uso posterior.
O resto é bem simples. O mestre lê uma linha de STDIN, repete todos os descritores de arquivo em $fds
e envia a linha para esse desciptor de arquivo ( printf ... >&$fd
).
O resultado é assim:
$ /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
Onde eu digitei hello
e world
.