这些是重现问题的步骤。
writer
:
#!/bin/bash
trap 'echo NoReader!' PIPE
cat > fifo
打开两个终端。我将用下面的>T1<
和>T2<
标题来表示它们,并用 来表示它们的提示$
。
>T1<
$ mkfifo fifo
$ bash writer
ABC
>T2<
$ cat fifo
ABC
^C
>T1<
DEF
$ echo $?
141
从man fifo
,
当进程尝试写入另一端未打开以供读取的 FIFO 时,会向该进程发送 SIGPIPE 信号。
当我进入时DEF
,FIFO 已经没有读取器了。所以我预计 SIGPIPE 上的陷阱在输入后会被触发DEF
并显示相应的NoReader!
消息。相反,该进程会默默终止。错误代码是141,这表明它确实被 SIGPIPE 终止了。
另一方面,执行这个newWriter
#!/bin/bash
trap 'echo NoReader!' PIPE
var=$(head -c 100000 /dev/urandom)
echo "$var" > fifo
在终端 1 和head -c 1 fifo
终端 2 确实触发了陷阱!但是,如果我只是从 urandom 中提取 1000 个字节而不是 100000 个字节,则不会触发陷阱。
我缺少什么?为什么第一个示例中没有触发陷阱writer
,而是在newWriter
100000 字节(而不是 1000 字节)中触发?
答案1
猫
陷阱处理程序未执行的原因bash
很简单,就是bash
没有收到该信号。它仅被发送到写入进程,即cat
。
如果是 shell 本身执行写入操作,则会执行陷阱处理程序:
#!/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
。