O termo para o que você está tentando realizar é multiplexação .
Isso pode ser realizado facilmente no bash, mas requer alguns recursos mais avançados do bash.
Eu criei um script baseado no seu, que eu acho que faz o que você está tentando realizar. 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ê de STDIN e grava seu identificador e a linha em STDOUT. Usamos em $BASHPID
vez de $$
como $$
não é atualizado para subshells (que é o que usaremos para iniciar manager
.
fds
é uma matriz que retém os descritores de arquivo apontando para os tubos STDIN dos vários manager
s gerados.
Em seguida, fazemos um loop e criamos 5 processos de gerente. Eu uso a for (( ))
sintaxe em vez da maneira que você estava fazendo, pois é mais limpo. Isso é específico do bash, mas várias das coisas que esse script faz são específicas do bash; portanto, é possível que você vá até o fim.
Em seguida, chegamos a exec {fd}> >(manager $i)
. Isso faz várias outras coisas específicas do bash.
O primeiro dos quais é {fd}>
. Isso pega o próximo descritor de arquivo disponível no número 10 ou depois dele, abre um canal com o lado de gravação 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çamento manager $i
e basicamente substitui o >(manager $i)
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 SO).
Portanto, supondo que o próximo número de descritor de arquivo disponível seja 10 e o gerenciador seja iniciado com o PID 1234, o comando exec {fd}> >(manager $i)
basicamente se torna exec 10>/proc/1234/fd/0
, e o bash agora tem o descritor de arquivo apontando para STDIN desse gerenciador.
Então, como o bash coloca esse número de descritor de arquivo $fd
, adicionamos esse descritor à matriz fds
para uso posterior.
O resto é bem simples. O mestre lê uma linha do STDIN, itera sobre todos os descritores de arquivo $fds
e envia a linha para o arquivo desciptor ( printf ... >&$fd
).
O resultado fica 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
.