あなたが達成しようとしていることの用語は多重化です。
これは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
は、STDINから単に読み取り、その識別子と行をSTDOUTに書き込むbash関数です。私たちは、使用$BASHPID
の代わり$$
として$$
、我々が起動するように使用されるものである(サブシェルのために更新されませんmanager
。
fds
は、manager
生成されたさまざまなのSTDINパイプを指すファイル記述子を保持する配列です。
次に、ループして5つのマネージャープロセスを作成します。私はfor (( ))
あなたがそれがきれいだったので、あなたがそれをしていた方法の代わりに構文を使用します。これはbash固有ですが、このスクリプトが行うことのいくつかはbash固有であるため、最後まで進む可能性があります。
次にに行きexec {fd}> >(manager $i)
ます。これにより、bash固有の処理がいくつか行われます。
最初のものは{fd}>
です。これにより、番号10以降で次に利用可能なファイル記述子が取得され、そのファイル記述子に割り当てられたパイプの書き込み側でパイプが開かれ、ファイル記述子番号が変数に割り当てられます$fd
。
>(manager $i)
起動manager $i
と基本的に代替>(manager $i)
そのプロセスのSTDINへのパスを持ちます。したがって、manager
PID 1234として起動された場合>(manager $i)
、/proc/1234/fd/0
(これはOSに依存します)に置き換えられる可能性があります。
したがって、次に使用可能なファイル記述子番号が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
。