Linux FIFO バッファリングは、リーダーとライターが呼び出される順序によって異なります。

Linux FIFO バッファリングは、リーダーとライターが呼び出される順序によって異なります。

私はfifoで読んで別のfifoに書き込む簡単なPythonスクリプトを書こうとしています。

次のコマンドを使用して2つのFIFOを作成しました。

$ mkfifo input
$ mkfifo output

次のコマンドを使用してスクリプトを呼び出します。

$ tail -f input | stdbuf -oL ../entropyCalc/entropy.py > output

、次のコマンドを使用してFIFOを観察しますoutput

$ tail -f output

その後、作家に次のように電話します。

$ echo "/path/to/a/valid/file" >> input

問題は、fifoが入力ファイルを処理した直後に結果を出力したいのですが、スクリプトを一度呼び出し(実行)したときにスクリプトを終了してから再実行することだけを観察することです。その後、すべてがうまくいきます。

要約:スクリプトの実行 - >リーダーの開始 - > fifoへの書き込みを実行すると、
リーダーに出力は表示されません。ただし、スクリプトの実行 - >リーダーの開始 - > fifoへの書き込みコマンドは出力を実行します。結果 -> スクリプトの終了 -> スクリプトの再実行input
tail -f output

結果がstdoutに書き込まれた後、システムはすぐにファイルに書き込もうとしているので、この動作の原因は何であるかわかりません。stdbuf -oLバッファリングを 1 行に制限するバッファリングを使用しない場合、バッファリングが発生すると予想されます。

Pythonスクリプトはシンプルなエントロピー計算機です。

#! /usr/bin/env python2

import sys, os
import numpy as np
from scipy.stats import entropy

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    line = line.strip()

    if not line == '':
        fname1 = open(line)
        fsize = os.path.getsize(line)
        f1 = np.frombuffer(fname1.read(fsize), dtype=np.uint8)
        value,counts = np.unique(f1, return_counts=True)
        print line,str(entropy(counts))
        sys.stdout.flush()

Ubuntu 18.04.3でbash 4.4を使用しています。

ベストアンサー1

あなたはtailそれを間違って使用しました。

あなたが観察するものは単に表すtail -f output広告したように。そして、あなたが使用するトラップがたくさんありますtail -f input

このtail誤用はスクリプトの動作の整合性を損なう可能性があります。詳しくは下記をご覧ください。

簡単な説明

使用に関する質問tail -f input

  • まずファイルの終わりを待ちます。
  • ファイルの終わりに最初到達すると(最初のファイル名プロバイダーが終了します)、最後の10個のファイル名のみがスクリプトに渡され、操作の整合性が破壊されます。
  • 到達するまでバッファリングされます。ファイルの終わりにより、対話型/希少ファイル名の入力は使用できません。

使用に関する質問tail -f output

  • まずファイルの終わりを待ちます。
  • ファイルの終わりに最初到達すると(最初のスクリプトが終了したとき)、これまでのスクリプト出力の最後の10行だけが提供され、動作の整合性が破壊されます。

tail -f output(出力脚が端子なのでバッファリングは問題になりません)

バラより結論として以下は回避策です。

長い説明

ジョブの説明はtail基本的には次のとおりです。前の10行出力ファイルの終わり".-fスイッチは"だけを追加します。以降に追加された内容」。

  • 主な目標を達成するには、tailファイルの終わりに達するまで入力を静かにして、無限に読み取る必要があります(最後の10行だけがバッファに残ります)。次に、バッファの最後の10行を出力にダンプしてから終了します(または同じ-f操作を続けます)。

今思い出させていただきます。ファイルが次に終わる管路アップストリームプログラムが終了するまで発生しません。1 ...

結果はtail -f output意志である、デザインによって、何もエクスポートせずにスクリプトの結果を自動的にバッファリングします...最初にスクリプトを終了する瞬間まで:ファイルの終わりが転送されtail -f output、その時点で出力が表示され始めます。

  • しかし、あなたが見るものは完全な出力ではありません今までは最後の10行だけ出力その瞬間。

    スクリプトに20個のファイル(一度に10個未満、次のトピックを参照)を分析するように依頼すると、スクリプトが最初に終了する前に最後の10個のファイルの分析結果のみを取得できます。これにより、スクリプト操作に対する期待(つまり整合性)が破られます。、その結果すべて実行された分析は出力に報告する必要があります。

  • この問題も影響を受けますtail -f input。 11個以上のファイル名を含むファイルのリストをinputパイプラインにダンプします。最初その結果、10個のサブ名だけがスクリプトに到達します。スクリプト操作の整合性違反再び。 2番目からはもう問題になりません。

物語はまだ終わっていません...

最初のファイルの終わりに達すると、tail -fステージングは​​続行されます-fその後、入力ファイルに追加されたすべての項目を出力します。

このステップでは入力ハンドルを閉じません。inotify入力リスナー文書、それから待ってください。プログラムが入力ファイルを書き込むか閉じるたびに、tail入力ハンドルが再度読み取られます。今読んだものをすべて印刷してください。) ファイルの最後2 に会うまで待機状態に戻ります。手動で終了するまですすぎ、繰り返しますtail -f

  • ここで一つの問題は、今読んだものをすべて印刷してください。また、一般的な出力バッファリングが適用されます。出力が端末でない場合。

    tail -f output出力分岐が端末であるため、ユーザー自身の使用には影響しません。tail -f inputただし、次の影響を受けます。

    • 複数のファイル名を対話形式で入力すると、cat > input終了するまで処理が開始されないことがわかりますcat
    • これはinput、時々ファイル名をエクスポートする長期実行プログラムのパイプラインも機能しないことを意味します。

結論として

tail -f input私の理解によると、ファイルの終わりを受け取らないようにスクリプトをマスクしたので、スクリプトは次のようになります。悪魔、ファイル名プロバイダプログラムが行ったり来たりすることができます。

tail -n +1 -fだから私の提案はこれを使ってtailファイルの終わりを無限に見つけないようにし、最後の10行の問題を取り除くことです。次に、それを使用してstdbuf問題になる可能性があるバッファリング3,4を制御します。

stdbuf -oL tail -n +1 -f input | ../entropyCalc/entropy.py > output 2>&1

その後、監視の観点から以下を使用します。

tail -n +1 -f output

または:

while true; do cat output; done

脚注

  • 1より正確には、アップストリームプログラムがパイプを閉じるときです。 (あなたの場合、tail -f outputスクリプトが終了したときにのみ発生します)
  • 2は、tail -f outputスクリプトを終了しない限り決して発生しません。第二時間。
  • 3スクリプトはすでに出力フェーズでラインバッファリングを実行しているため、そこにいる必要はありませんstdbuf
  • 4標準エラーリダイレクトは、2>&1監視端末にもスクリプトエラーが表示されることを保証します。

おすすめ記事