SIGPIPE と bash パイプフェイル

SIGPIPE と bash パイプフェイル

Linux 上の SIGPIPE をより深く理解しようとしています。

私はこの実験を実行しました:{ ls -al /tmp/ ; echo "$?" 1>&2 ; } | head そして、 echo が出力されまし141た。これは、 で終了するプロセスに与えられる終了コードであると理解しています。SIGPIPE 以前は、 のニュアンスを理解せずにこれを何度も行っていましたSIGPIPEが、通常は で実行していたset -eEuo pipefailので、壊れたパイプが原因でコードが常に失敗しない理由を理解しようとしていました... そこで、この別の実験を実行しました:( set -o pipefail; { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head; )そして、そのとき echo で 0 が得られました... がpipefail有効になっている場合、 が抑制されることを意味しますかSIGPIPE? それとも、ここで何が起こっているのか私が誤解していますか?

答え1

lsは、出力が印刷されるものより長いhead場合でも、終了してパイプを切断する前に、すべての出力を書き込むことができます。これは次の理由によるものです。lshead

  • head最終的に印刷される量よりも多く読まれる可能性がある。
  • いずれにせよ、パイプ用のバッファが存在します。

SIGPIPE は、壊れたパイプへの実際の書き込みによってトリガーされます。終了ls前にすべての出力を書き込むことができればhead、SIGPIPE をトリガーする書き込み行為は発生しません。

または、終了するls前にすべての出力を書き込むことができない場合がありますhead。その場合、さらに書き込もうとすると、SIGPIPE が返されます。

lsとが並行して実行されると、一般的に競合状態が発生すると思います。 からの特定の出力がランダムに SIGPIPE をトリガーしたりトリガーしなかったりするheadことがあります。ls

yesの代わりに を試してくださいls …:

{ yes ; echo "$?" 1>&2 ; } | head

または

( set -o pipefail; { yes ; echo "$?" 1>&2 ; } | head; )

yesそれ自体では終了しない出力を生成するため、head終了した後は常に SIGPIPE をトリガーする書き込み動作が発生します。上記の各コマンドは141確実に提供します。

これは とは何の関係もありませんpipefail

関連情報