Tシャツの予測不可能な行動の説明

Tシャツの予測不可能な行動の説明

繰り返し実行されるプログラムの出力を合計するスクリプトのテスト中に理解できない動作が見つかりました。これを再現するには、out私のプログラムの出力を表すテキストファイルを作成しsum、このファイルは前の実行から返された値の合計を保持し、そのコピーで始まりますout

cat > out << EOF
2 20
5 50
EOF
cp out sum

実行中に奇妙なことが起こります

paste out sum | awk '{$1 += $3; $2 += $4; NF = 2; print}' | tee sum

複数回(15〜20回かかることがあります)実行するたびに、コマンドはsumその値に値を追加しoutて結果を再作成する必要がありますsum。私が得るものは予測不可能な回数だけ働いたsum

2 20
5 50

後で学びました。作業中の同じファイルに出力をリダイレクトまたはティーイングすることはできません。一時ファイルを使用すると問題は解決しましたが、この動作はまだ混乱しています。

  • … | tee sum限られた回数の繰り返しでも機能しますが、… > sum上書きしないのはなぜですかsum

  • なぜ期待どおりに動作しないのですか?

ベストアンサー1

これ、

paste out sum | awk ... | tee sum

競争条件があります。読むためにpaste開いて、書くために開いて、切ります。シェルはほぼ同時に起動するため、最初にファイルを開くシェルによって異なります。sumtee

もちろん、実際には、シェルは特定の順序で一度に1つずつユーティリティを起動する必要があります。左から右に実行される可能性があるため、paste最初に実行される可能性が高いかもしれませんが、これは実装の詳細であり、とにかく実行するタイミングはOSスケジューラによって決定されます。

先に進むと、pasteデータはそのまま残り、データを読み取るのに十分な時間があるファイルが開きます。ファイルを読み込む前に開くと、空のteeファイルが表示されます。pastepaste

ここでは、

paste out sum | awk ... > sum

シェルは書き込みsum用に開き、切り捨てられます。これはstartと並行して実行できますが、切り捨てにはpastesumのユーティリティの起動が含まれていないため、最初に発生する可能性があります。 (リダイレクトを処理するルールと、そのようなパイプラインでコマンドが開始される順序があるかどうかはわかりませんが、それに依存しません。)

spongeこの問題を解決するツールがあります。それに関する質問)。得られた入力を収集し、入力が閉じた後にのみ書き込みます。これはsum常に正しく更新する必要があります。

paste out sum | awk ... | sponge sum

おすすめ記事