Der Begriff für das, was Sie erreichen möchten, lautet Multiplexing .
Dies kann mit bash relativ einfach erreicht werden, erfordert jedoch einige erweiterte bash-Funktionen.
Ich habe ein Skript erstellt, das auf Ihrem basiert und das das tut, was Sie erreichen wollen. Ich werde es unten erklären.
#!/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
ist eine Bash-Funktion, die einfach aus STDIN liest und ihren Bezeichner und die Zeile in STDOUT schreibt. Wir verwenden $BASHPID
anstelle von $$
as, $$
das für Subshells nicht aktualisiert wird (was wir zum Starten verwenden werden) manager
.
fds
ist ein Array, das die Dateideskriptoren enthält, die auf die STDIN-Pipes der verschiedenen ausgelösten manager
s verweisen .
Dann durchlaufen wir 5 Managerprozesse und erstellen diese. Ich verwende die for (( ))
Syntax anstelle der Art und Weise, wie Sie sie ausgeführt haben, da sie sauberer ist. Dies ist bash-spezifisch, aber einige der Dinge, die dieses Skript ausführt, sind bash-spezifisch.
Als nächstes kommen wir zu exec {fd}> >(manager $i)
. Dies führt einige weitere bash-spezifische Dinge aus.
Das erste davon ist {fd}>
. Dies ermittelt den nächsten verfügbaren Dateideskriptor ab Nummer 10, öffnet eine Pipe mit der Schreibseite der Pipe, die diesem Dateideskriptor zugewiesen ist, und weist der Variablen die Dateideskriptornummer zu $fd
.
Das >(manager $i)
startet manager $i
und ersetzt im Grunde >(manager $i)
mit einem Pfad zu einem STDIN dieses Prozesses. Wenn also manager
als PID 1234 gestartet wurde, wird dies >(manager $i)
möglicherweise durch ersetzt /proc/1234/fd/0
(dies ist vom Betriebssystem abhängig).
Angenommen, die nächste verfügbare Dateideskriptornummer ist 10, und der Manager wird mit der PID 1234 gestartet, der Befehl wird im exec {fd}> >(manager $i)
Grunde genommen zu exec 10>/proc/1234/fd/0
und in der Bash wird nun der Dateideskriptor auf die STDIN dieses Managers gezeigt.
Da bash diese Dateideskriptornummer eingibt $fd
, fügen wir diesen Deskriptor zur fds
späteren Verwendung zum Array hinzu .
Der Rest ist ziemlich einfach. Der Master liest eine Zeile aus STDIN, durchläuft alle Dateideskriptoren in $fds
und sendet die Zeile an diesen Dateideskriptor ( printf ... >&$fd
).
Das Ergebnis sieht so aus:
$ /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
Wo ich getippt habe hello
und world
.
echo -- "$line"
oderprintf "%s\n" "$line"
- aber warum Sie verwenden müssten,--
wenn das nächste Argument fest codiert ist (und nicht mit beginnt-
)?tee
undbash
:Wenn die Anzahl der Manager konfigurierbar sein soll oder wenn die Ausgabe von verschiedenen Managern nicht gemischt werden soll:
quelle