Le terme pour ce que vous essayez d'accomplir est le multiplexage .
Cela peut être accompli assez facilement dans bash, mais cela nécessite des fonctionnalités bash plus avancées.
J'ai créé un script basé sur le vôtre qui, je pense, fait ce que vous essayez d'accomplir. Je vais l'expliquer ci-dessous.
#!/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
est une fonction bash qui lit simplement depuis STDIN et écrit son identifiant et la ligne dans STDOUT. Nous utilisons $BASHPID
au lieu de $$
as qui $$
n'est pas mis à jour pour les sous-coquilles (c'est ce que nous allons utiliser pour lancer manager
.
fds
est un tableau qui contiendra les descripteurs de fichiers pointant vers les canaux STDIN des différents manager
s générés.
Ensuite, nous bouclons et créons 5 processus de gestion. J'utilise la for (( ))
syntaxe au lieu de la façon dont vous le faisiez car elle est plus propre. Ceci est spécifique à bash, mais plusieurs des choses que ce script fait sont spécifiques à bash, donc aussi bien aller jusqu'au bout.
Ensuite, nous y arrivons exec {fd}> >(manager $i)
. Cela fait plusieurs choses plus spécifiques à bash.
Le premier est {fd}>
. Cela saisit le descripteur de fichier suivant disponible sur ou après le numéro 10, ouvre un canal avec le côté écriture du canal affecté à ce descripteur de fichier et attribue le numéro de descripteur de fichier à la variable $fd
.
Le >(manager $i)
lance manager $i
et se substitue essentiellement >(manager $i)
avec un chemin vers un STDIN de ce processus. Donc, si a manager
été lancé en tant que PID 1234, il >(manager $i)
pourrait être remplacé par /proc/1234/fd/0
(cela dépend du système d'exploitation).
Donc, en supposant que le prochain numéro de descripteur de fichier disponible est 10 et que le gestionnaire est lancé avec le PID 1234, la commande exec {fd}> >(manager $i)
devient essentiellement exec 10>/proc/1234/fd/0
et bash a maintenant un descripteur de fichier pointant vers STDIN de ce gestionnaire.
Puis, puisque bash place ce numéro de descripteur de fichier $fd
, nous ajoutons ce descripteur au tableau fds
pour une utilisation ultérieure.
Le reste est assez simple. Le maître lit une ligne à partir de STDIN, parcourt tous les descripteurs de fichiers dans $fds
et envoie la ligne à ce fichier desciptor ( printf ... >&$fd
).
Le résultat ressemble à ceci:
$ /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
Où j'ai tapé hello
et world
.