問題を再現する手順は次のとおりです。
writer
:
#!/bin/bash
trap 'echo NoReader!' PIPE
cat > fifo
2 つの端末を開きます。以下の>T1<
タイトルとタイトルを使用して>T2<
これを表現し、プロンプトを使用してそれを表現します$
。
>T1<
$ mkfifo fifo
$ bash writer
ABC
>T2<
$ cat fifo
ABC
^C
>T1<
DEF
$ echo $?
141
~からman fifo
、
SIGPIPE 信号は、もう一方の端で読み取るために開いていない FIFO に書き込もうとすると、プロセスに送信されます。
私が入力したとき、DEF
FIFOにリーダーが残っていませんでした。そのため、入力後にSIGPIPEのトラップがトリガーされ、DEF
適切なNoReader!
メッセージが表示されると予想しました。代わりに、プロセスは自動的に終了します。エラーコードは141、これは実際にSIGPIPEによって終了されたことを示します。。
一方、これを実行するとnewWriter
#!/bin/bash
trap 'echo NoReader!' PIPE
var=$(head -c 100000 /dev/urandom)
echo "$var" > fifo
head -c 1 fifo
実際に第1ターミナルと第2ターミナルでトラップが発動されます!ただし、urandomから100000バイトではなく1000バイトのみを抽出すると、トラップはトリガされません。
私は何を見逃していますか?最初の例では、トラップはトリガーされていませんが、1000バイトではなく100000バイトwriter
でトリガーされるのはなぜですか?newWriter
答え1
猫
トラップハンドラが実行されない理由は、単に信号が受信されなかったためbash
です。bash
書き込みプロセスにのみ送信されますcat
。
シェル自体が書き込み操作を実行すると、トラップハンドラが実行されます。
#!/bin/bash
exec 3>fifo
trap 'echo NoReader!' PIPE
while IFS= read -r -d '' -n 1 input; do
printf %s "$input" >&3 || break
done </dev/urandom
頭
strace
呼び出しの他の動作の理由を示しますhead
。 FIFOバッファ4096バイト(私のシステムでは、何らかの方法でこの値をカーネルから取得できます)。したがって、-c 4096
butを使用してもエラーは発生しないでください4097
。