stdinをstdoutとstderrにコピーしますが、同時に同期してコピーします。

stdinをstdoutとstderrにコピーしますが、同時に同期してコピーします。

生産者の標準出力をコピーして両方の消費者に同時に供給する必要があります。同期ファッション。

                        consumer 1
producer | duplicator | 
                        consumer 2

これは次の方法で簡単に実行できますtee

((cat f.txt | tee /dev/stderr | ./cons1.py >&3) 2>&1 | ./cons2.py) 3>&1

または名前付きパイプを介して:

mkfifo fifo1 fifo2
cat f.txt | tee fifo1 fifo2 >/dev/null &
< fifo1 ./cons1.py &
< fifo2 ./cons2.py

dup.cあるいは、最後に同じことを行うプログラムを書くこともできます。

#include <stdio.h>
int main()
{
    char *line = NULL;
    size_t size;
    while (getline(&line, &size, stdin) != -1) {
        fprintf(stdout, "%s", line);
        fprintf(stderr, "%s", line);
    }
    return 0;
}

それから:

((cat f.txt | ./dup | ./cons1.py >&3) 2>&1 | ./cons2.py) 3>&1

しかし、消費者 1 が消費者 2 より速い場合、問題が発生します。。たとえば、消費者 1 はすでに 50,000 行にあり、消費者 2 は 17,000 行にあります。

私のシステムのために両方の消費者が同じ回線にいる必要があるため、より速い消費者を制限する必要があります。。私はこれがLinux標準ツールを介しては不可能かもしれないことを知っています。ただし、少なくともこのdup.cアプローチを使用している場合は可能です。これを達成する方法について提案がありますか?ありがとうございます!

答え1

欲しいものを達成する普遍的な方法はありません。

基本的な問題は、パイプが一方向であり、生産者は消費者の現在の状態とパイプに送信されたデータが消費されたかどうかを知らないことです。

したがって、この制限を解決するには2つの方法があり、両方が必要です。先験的にデータと消費者について知っておくべきこと:

  • 生産(または元の生産者から消費者パイプへの転送)を遅くして、消費者が常に同期するようにします。つまり、各生産ラインが消費のために送信された後に次のラインを送信すると、消費者の100%が処理を完了するのに十分な時間がかかります(TiberiusKirkの提案と同様)。

  • 消費者の処理の進行状況を確認して、入力行が消費されたことを確認します。これには、消費者からのフィードバックまたは出力が必要であり、存在する場合も存在しない場合もあり、実行可能に処理される場合もありません。

第1の解決策は、入力データの処理時間推定のための適切な下限を必要とし、第2の解決策は消費者からの一種のフィードバックを必要とする。

答え2

ファイルの読み込み速度を遅くして、より高速な消費者が待つことを可能にするオプションはありますか?

while read LINE; do
   echo "$LINE" | tee /dev/stderr | ./consumer1.py ; ) 2>&1 | ./consumer2.py
   sleep 0.01
done < "file.txt"

ただし、一部のシステムでは、1秒未満の睡眠時間はオプションではありません。

関連情報