複数の同時共同プロセスを持つことはできますか?

複数の同時共同プロセスを持つことはできますか?

これ意図以下のテストスクリプト1の目的は、「外部」共同プロセス(実行中)を開始しseq 3、ループからこの共同プロセスのデータを読み取りwhile、読み取った各行について、外部ループの現在の反復を識別する行を印刷し、「内部」 「共同プロセスを開始することです。 " "コプロセス(seq新しいパラメータを使用して実行中)は、ネストされたwhileループからこの内部コプロセスを読み取り、次にこの内部コプロセスをクリーンアップします。ネストされたwhileループは、内部コプロセスで読み取られる各行のいくつかの出力を印刷します。

#!/bin/bash
# filename: coproctest.sh
PATH=/bin:/usr/bin

coproc OUTER { seq 3; }
SAVED_OUTER_PID="${OUTER_PID}"

exec {OUTER_READER}<&"${OUTER[0]}"
while IFS= read -r -u "${OUTER_READER}" OUTER_INDEX; do

    printf -- '%d\n' "${OUTER_INDEX}"

    START=$(( OUTER_INDEX * 1000000 ))
    FINISH=$(( START + OUTER_INDEX ))

    # (
      coproc INNER { seq "${START}" "${FINISH}"; }
      SAVED_INNER_PID="${INNER_PID}"
      exec {INNER_READER}<&"{INNER[0]}"

      while IFS= read -r -u "${INNER_READER}" INNER_INDEX; do
          printf -- '    %d\n' "${INNER_INDEX}"
      done

      exec {INNER_READER}<&-

      wait "${SAVED_INNER_PID}"
    # )

done
exec {OUTER_READER}<&-
wait "${SAVED_OUTER_PID}"

このスクリプトを実行すると、次のような結果が得られます。

% ./coproctest.sh
1
./coproctest.sh: line 30: warning: execute_coproc: coproc [12523:OUTER] still exists
./coproctest.sh: line 19: INNER_READER: ambiguous redirect
./coproctest.sh: line 21: read: : invalid file descriptor specification
./coproctest.sh: line 25: INNER_READER: ambiguous redirect
2
./coproctest.sh: line 19: INNER_READER: ambiguous redirect
./coproctest.sh: line 21: read: : invalid file descriptor specification
./coproctest.sh: line 25: INNER_READER: ambiguous redirect
3
./coproctest.sh: line 19: INNER_READER: ambiguous redirect
./coproctest.sh: line 21: read: : invalid file descriptor specification
./coproctest.sh: line 25: INNER_READER: ambiguous redirect

両方のコメント行のコメントを削除すると、ほぼ同じ結果が表示されます。


質問1:複数の共同プロセスを同時に実行できますか?

質問2:それでは、必要な出力を得るために上記のスクリプトをどのように変更する必要がありますか?


1コプロセッシングを始めたばかりだが、まだ理解できない部分が多いです。したがって、スクリプトには不正確な、不器用な、または不要なコードが含まれていることがほぼ確実です。あなたの回答に自由にコメントを提示するか、これらの弱点を修正してください。

答え1

マニュアルの最後の部分の「BUGS」セクションでbash

一度に1つのアクティブな共同プロセスしか存在できません。

答え2

Q1:同時に複数の共同プロセスを実行できますか?

Bash v4以降(現在v5を含む)には@Kusalanandaが指摘したように、正式なものはありません。

しかし、それはあなたに言うことができます。可能警告にもかかわらず、作業は確かに保証されておらず、YMMVです。ねえより多くの洞察を得るために。

Q2:もしそうなら、期待した出力を得るために上記のスクリプトをどのように修正する必要がありますか?

それ可能(上記のように)次の問題が解決した場合は正常に動作します。

exec {INNER_READER}<&"{INNER[0]}"  # <-- lacks the '$' sign for the 'INNER[0]' variable

その結果は次のとおりです。

./coproctest.sh: line 19: INNER_READER: ambiguous redirect

メッセージも同様です。

./coproctest.sh: line 21: read: : invalid file descriptor specification

情報。

問題を解決して警告を捨てると私に役立ちました。

その他の注意事項は次のとおりです。

  • coprocサブプロセス(サブシェル、コマンド、またはスクリプト)に渡す必要がない限り、ファイル記述子を繰り返す必要はありません。
  • seqコマンドは自然にすばやく完了し、自動変数が使用される前に消えるので、これを行うことです。行った方法で実行すると、これらの冗長ファイル記述子はすべての後続のコマンドとバックグラウンドプロセスによって継承されます。これは、補助プロセスが実際に入力パイプを使用し、終了する前に閉じるのを待つ場合には望ましくない可能性があります。したがって、この問題を解決する別の方法は同期メカニズムを使用することです。たとえば、OUTERセカンダリプロセスを作成し、{ seq 3; exec >&-; read; }プライマリスクリプトの入力を使用して、セカンダリecho >&${OUTER[1]}; wait "${OUTER_PID}"プロセスを続行readするようにしますwait。変数が消えるwait前に実行が行われるという保証はありません$OUTER_PID。この場合、警告メッセージをミュートまたは完全に無視して、次のものを使用できます。|| true
  • 個人的な注意事項として、同時に複数の共同プロセスを実行することを決定した場合は、次のことを再実装できることをお知らせします。荒いcoprocバックグラウンドプロセスでBash v3構文と名前付きFIFOを使用し、mkfifoLinuxでmkfifosトリックの代わりにプロセスオーバーライドを使用するのと同じです。 Bash v4構文を使用すると、あまり複雑ではありませんが、まだ難しい作業です。

関連情報