ときにtrue
終了し、パイプの読み出し側が閉じられているが、yes
書き込み側に書き込みしようとし続けます。この状態は「壊れたパイプ」と呼ばれ、カーネルがにSIGPIPE
信号を送信しyes
ます。yes
このシグナルに関して特別なことは何もしないので、殺されます。シグナルを無視した場合、そのwrite
呼び出しはエラーコードで失敗しますEPIPE
。これを行うプログラムは、EPIPE
書き込みに気づいて停止するように準備する必要があります。そうしないと、無限ループに入ります。
その場合はstrace yes | true
1を、あなたは両方の可能性のための準備カーネルを見ることができます:
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 4096) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17556, si_uid=1000} ---
+++ killed by SIGPIPE +++
strace
デバッガAPIを介してイベントを監視しています。デバッガAPIは、最初にエラーで返されるシステムコールについて通知し、次に信号について通知します。yes
ただし、の観点からは、信号が最初に発生します。(技術的には、カーネルが制御をユーザー空間に戻した後、それ以上のマシン命令が実行される前にシグナルが配信されるためwrite
、Cライブラリの「ラッパー」関数errno
はアプリケーションに設定して戻る機会を得ません。)
1悲しいことに、strace
Linux固有です。ほとんどの最近のUnixには、似たようなことをするコマンドがありますが、多くの場合、名前が異なります。おそらく、syscall引数を完全にデコードしません。
yes | tee >(true) >/dev/null
tee
すべてのライターが死ぬまで継続するので、期待どおりに動作しますtrue
。そのため、終了しても完全に混乱することはありません。