Terminem, który próbujesz osiągnąć, jest multipleksowanie .
Można to zrobić dość łatwo w bash, ale wymaga to bardziej zaawansowanych funkcji bash.
Stworzyłem skrypt oparty na twoim, który moim zdaniem robi to, co próbujesz osiągnąć. Wyjaśnię to poniżej.
#!/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
managerto funkcja bash, która po prostu odczytuje ze STDIN i zapisuje swój identyfikator i linię do STDOUT. Używamy $BASHPIDzamiast, $$ponieważ $$nie jest aktualizowany dla podpowłoki (co będziemy używać do uruchomienia manager.
fdsto tablica, która będzie przechowywać deskryptory plików wskazujące na potoki STDIN różnych managers spawnowanych.
Następnie wykonujemy pętlę i tworzymy 5 procesów menedżera. Używam for (( ))składni zamiast tego, jak to robiłeś, ponieważ jest czystsza. Jest to specyficzne dla bash, ale kilka rzeczy, które robi ten skrypt, jest specyficzne dla bash, więc równie dobrze może pójść na całość.
Następnie przechodzimy do exec {fd}> >(manager $i). Robi to jeszcze kilka rzeczy związanych z bash.
Pierwszy z nich to {fd}>. Spowoduje to pobranie następnego dostępnego deskryptora pliku na numer 10 lub później, otwarcie potoku ze stroną zapisującą potoku przypisaną do tego deskryptora pliku i przypisanie numeru deskryptora pliku do zmiennej $fd.
Do >(manager $i)premiery manager $ii zasadniczo substytuty >(manager $i)o ścieżkę do standardowego wejścia tego procesu. Więc jeśli managerzostał uruchomiony jako PID 1234, >(manager $i)może zostać zastąpiony /proc/1234/fd/0(to zależy od systemu operacyjnego).
Zakładając, że następnym dostępnym numerem deskryptora pliku jest 10, a menedżer jest uruchamiany z PID 1234, polecenie w exec {fd}> >(manager $i)zasadzie staje się exec 10>/proc/1234/fd/0, a bash ma teraz deskryptor pliku wskazujący STDIN tego menedżera.
Następnie, ponieważ bash wstawia numer tego deskryptora pliku $fd, dodajemy ten deskryptor do tablicy w fdscelu późniejszego użycia.
Reszta jest dość prosta. Master odczytuje wiersz ze STDIN, iteruje wszystkie deskryptory plików $fdsi wysyła wiersz do tego desciptor pliku ( printf ... >&$fd).
Wynik wygląda następująco:
$ /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
Gdzie wpisałem helloi world.