bash、リダイレクトループから戻っている間、安全ですか?

bash、リダイレクトループから戻っている間、安全ですか?

リダイレクトされたループから戻ります。

「ファイル」の書き込みバッファについて心配する必要があるかどうかわかりません。

function f {
    i=1
    while :
    do
        echo aaaaaaaaaaaaabbbbbbbbbbbbbbbbb
        ((i++))
        if [ $i -gt 3 ]
        then
            return    # return while redirected
        fi
    done >> file    # writing to file
}

f

注:この関数は、リダイレクトループから返されないように簡単に書き換えることができることを知っています。しかし、これはこの質問の目的のための単純化された例です。

だから改善しようとしないでください。これパスワード。

私は解決策にも興味がありません。

私の唯一の質問は、私が特に知る必要があるものですか?ファイル記述子が正しく閉じられていないようです。あるいは、時にはバッファの半分(例えば「aaaaaa」)だけがファイルに書き込まれると予想されるかもしれません。

これが本当に悪い考えなのか、そしてその理由が何なのか気になります。それとも、予期しない競争条件や同様の状況なしで動作する可能性がありますか? (しかしまた「これ、このパターンを書かなければならないからこれは悪い」などの答えは望まない。)

答え1

bashに組み込まれたコマンド(または組み込みかどうかにかかわらず同じコマンドを2回呼び出す場合)でも、各コマンドには独自の書き込みバッファがありますが、コマンド間に共有書き込みバッファはありません。

ksh93がいくつかのI / O最適化を実行することが知られているにもかかわらず(たとえば、事前に読み込み、一部のデータを共有するなど)入力する若干のエラーが発生する))、こんなことはしないでください。

したがって、そのような点では安全です。コマンドが完了すると(yoursなどecho aaaaaaaaaaaaabbbbbbbbbbbbbbbbb)、バックグラウンドで実行されている無人プロセスを分岐しないと仮定すると、すべてのI / Oが完了することが保証されます。

しかし、いくつかの注意事項があります。次の関数で:

f() {
  {
    echo x
    return
    echo y
  } > file
  echo something else
}

Bourneシェル(およびBourneシェルのみ)では、return内部コマンドグループの出力は破損しますが、古代シェルのように関数から返されるのではなく、コマンドグループはリダイレクトのためにサブシェルで実行されます(したがって表示されますsomething else)。

このような最新のシェルではこれはもう発生しませんが、bash次のように書くと、bashでも同じ問題が発生します。

f() {
  (
    echo x
    return
    echo y
  ) > file
  echo something else
}

または

f() {
  {
    echo x
    return
    echo y
  } | tr xy ab
  echo something else
}

特定のコマンドが待たない状況があることに注意してください。存在する:

f() {
  {
    echo >(sleep 1; echo x)
    return
  } > file
}
f; cat file

以前に実行されたxため、表示されないことがあります。catecho x

一部のシェル(ではありませんがbash)には、パイプラインコンポーネントと同様の潜在的な問題があります(最も右側のものを除く)。

関連情報