echo 与 echo|cat 读取/写入 FIFO(管道)时的不同行为

Different behavior with echo vs echo|cat when reading to / writing from FIFOs (pipes)

我试图理解为什么 echo 在 bash 脚本中使用时表现不同于 echo "Hi"|cat 的原因,管道损坏

行为 :

  1. echo 立即终止脚本
  2. echo "Hi"|cat 管道终止但脚本继续

示例复制步骤

script_with_echo.sh :

#!/bin/bash
mkfifo ii
cat<ii >/dev/null & echo "KILL : $!"
exec 3>ii
rm ii
while true; do read LINE; echo "$LINE" >&3; echo "$?">/some/external/file;done

script_with_echo_cat.sh :

#!/bin/bash
mkfifo ii
cat<ii >/dev/null & echo "KILL : $!"
exec 3>ii
rm ii
while true; do read LINE; echo "$LINE"|cat>&3; echo "$?">/some/external/file;done
  1. 运行 终端 1 上的脚本(注意 KILL : <PID>
  2. 将一些示例行输入到终端 1 并验证 0(成功退出代码)正在写入 /some/external/file
  3. 运行 kill -9 <PID> 来自终端 2
  4. 在terminal-1输入另一条采样线
    • 如果 script_with_echo.sh 在步骤 1 中被执行,脚本立即终止(并且没有错误代码写入 /some/external/file
    • 如果在步骤 1 中执行了 script_with_echo_cat.sh脚本将正常继续(并且对于每个后续示例行输入,错误代码 141(SIGPIPE ) 正在写入 /some/external/file,这是预期的)

为什么会出现这种不同的行为?

why echo behaves differently than echo "Hi"|cat when used in a bash script

echo >&3 的情况下,当连接到第 3 个文件描述符的管道关闭时,bash 进程将被 SIGPIPE 杀死。这主要是因为 echo 是一个内置命令 - 它由 bash 本身执行,没有任何 fork()ing.

echo | cat >&3的情况下,当连接到第3个文件描述符的管道关闭时,子进程catSIGPIPE杀死,在这种情况下父进程继续活下去,所以 Bash 可以处理退出状态。

比较 strace -ff bash -c 'mkfifo ii; cat <ii >/dev/null & pid=$! ; exec 3>ii ; kill $pid ; rm ii ; echo something >&3'....; /bin/echo something >&3'