複数のプロセス間の通信

複数のプロセス間の通信

私はManager()関数を別々のプロセスとしてx回実行するbashスクリプトを持っています。スクリプト内のすべてのManager()プロセスにメッセージを渡すには?

匿名パイプについて読みましたが、メッセージを共有する方法がわかりません。名前付きパイプを使ってみましたが、プロセスごとに別々の名前付きパイプを作成する必要があると思いますか?

最もエレガントな方法は何ですか?

これは私のコードです。

#!/bin/bash

manager () {
    while :
    do
        echo "read what has been passed to \$line"
    done
}

x=1
while [ $x -le 5 ]
do
  manager x &
  x=$(( $x + 1 ))
done


while :
do
while read line
do
  echo "What has been passed through the pipe is ${line}"
  # should pass $line to every manager process

done < $1
done

exit 0

答え1

あなたが達成したいことを指す用語は次のとおりです。再利用

これは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

fdsmanagersによって生成されたさまざまなSTDINパイプを指すファイル記述子を保持する配列。
次に、5つの管理者プロセスを繰り返して作成します。私はfor (( ))あなたが使用する方法の代わりに構文を使用しています。なぜならそれはよりきれいだからです。これはbashに固有のものですが、スクリプトが実行する操作の一部はbashに固有のものであるため、最後まで進むことをお勧めします。
 

次に私たちは到着しましたexec {fd}> >(manager $i)。これはより多くのbash関連タスクを実行します。
そのうちの最初のものです{fd}>。これは、番号が10以上の次の使用可能なファイル記述子を取得し、パイプを開き、パイプの書き込み先を対応するファイル記述子に割り当て、ファイル記述子番号を変数に割り当てます$fd

プロセスのSTDINパスを開始し>(manager $i)manager $iデフォルトで交換します。>(manager $i)したがって、managerPID 1234から起動すると(オペレーティングシステムに応じて)>(manager $i)交換できます。/proc/1234/fd/0

したがって、次の使用可能なファイル記述子番号が10で、管理者がPID 1234で始まると仮定すると、コマンドはデフォルトで実行され、exec {fd}> >(manager $i)bashexec 10>/proc/1234/fd/0には管理者のSTDINを指すファイル記述子があります。
次に、bashは対応するファイル記述子番号をに入れるので、後で使用できるように$fdその記述子を配列に追加します。fds
 

残りはとても簡単です。マスターはSTDINから1行を読み取り、その中のすべてのファイル記述子を介して繰り返し、その行$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

答え2

teeそしてbash

cat foo | tee >(manager) >(manager) >(manager) >(manager) >(manager) >/dev/null

管理者の数を設定できる必要がある場合、または複数の管理者の出力が混在しないようにする場合:

export -f manager
cat foo | parallel --pipe --tee manager ::: {1..10}

関連情報