![SIGPIPE と bash パイプフェイル](https://rvso.com/image/231080/SIGPIPE%20%E3%81%A8%20bash%20%E3%83%91%E3%82%A4%E3%83%97%E3%83%95%E3%82%A7%E3%82%A4%E3%83%AB.png)
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
場合でも、終了してパイプを切断する前に、すべての出力を書き込むことができます。これは次の理由によるものです。ls
head
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
。