Термін того, що ви намагаєтеся зробити, - це мультиплексування .
Це може бути досягнуто досить легко в bash, але для цього потрібні деякі більш досконалі функції bash.
Я створив сценарій, заснований на вашому, який, на мою думку, робить те, що ви намагаєтеся виконати. Я поясню це нижче.
#!/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
це функція bash, яка просто зчитує з STDIN і записує свій ідентифікатор і рядок в STDOUT. Ми використовуємо $BASHPID
замість того $$
, $$
що не оновлюється для передплатежів (що ми будемо використовувати для запуску manager
.
fds
являє собою масив, який буде містити дескриптори файлів, що вказують на STDIN-труби різних manager
s, що породилися.
Потім ми перебираємо і створюємо 5 процесів менеджера. Я використовую for (( ))
синтаксис замість того, як ви робили це, оскільки він чистіший. Це специфічно для bash, але кілька речей, які цей скрипт робить, є специфічними для удару, тому вони можуть пройти весь шлях.
Далі ми добираємось exec {fd}> >(manager $i)
. Це робить ще кілька конкретних речей.
Перший з яких - це {fd}>
. Це захоплює наступний доступний дескриптор файлу на або після номера 10, відкриває трубку зі стороною запису труби, призначеної цьому дескриптору файлу, і присвоює номер дескриптора файлу змінній $fd
.
У >(manager $i)
запусках manager $i
і в основному замінники >(manager $i)
з шляхом до STDIN цього процесу. Отже, якщо він manager
був запущений як PID 1234, він >(manager $i)
може бути замінений /proc/1234/fd/0
(це залежить від ОС).
Таким чином, якщо припустити, що наступний доступний номер дескриптора файлу - 10, і менеджер запускається з PID 1234, команда в exec {fd}> >(manager $i)
основному стає exec 10>/proc/1234/fd/0
, і bash тепер має дескриптор файлів, що вказує на STDIN цього менеджера.
Потім, оскільки bash $fd
додає номер дескриптора файлу , ми додаємо цей дескриптор до масиву fds
для подальшого використання.
Решта - досить проста. Ведучий зчитує рядок із STDIN, повторює всі дескриптори файлів у $fds
і посилає рядок до цього дескриптора файлу ( printf ... >&$fd
).
Результат виглядає приблизно так:
$ /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
Де я набрав hello
і world
.