qye*_*cst 5 shell bash pipe command
为什么命令可以{ echo err >&2; echo out >&1; } | :
打印“err”,而第二个命令却不能?
容器中的一些测试:
这也发生在主机 CentOS 8.0.1905、Debian 11.4 中。
~# { echo err >&2; echo out >&1; } | :
err
~# { echo out >&1; echo err >&2; } | :
~#
Run Code Online (Sandbox Code Playgroud)
不使用:
似乎是正确的:
~# { echo out >&1; echo err >&2; } | sed 's/.*/-&-/'
err
-out-
~#
Run Code Online (Sandbox Code Playgroud)
但在另一台主机CentOS 7.7.1908(bash/4.2.46)中打印:
~# { echo out >&1; echo err >&2; } | :
err
~#
Run Code Online (Sandbox Code Playgroud)
和...之间的不同
{ echo err >&2; echo out >&1; } | :
Run Code Online (Sandbox Code Playgroud)
... 和
{ echo out >&1; echo err >&2; } | :
Run Code Online (Sandbox Code Playgroud)
echo
...是两次调用的顺序。该订单的重要性仅在于第一个订单的执行速度。echo
管道的两侧{ ...; }
和:
是同时启动的,并且:
不从其标准输入流读取。这意味着管道一旦:
终止就会被拆除,几乎是立即拆除。
如果管道被拆除,则没有管道缓冲区可供echo out >&1
写入。当echo
尝试写入不存在的管道时,管道的左侧会因接收 PIPE 信号而死亡。
如果它echo err >&2
在执行之前就死掉了,那么就没有输出。
所以:
您将始终获得err
输出,{ echo err >&2; echo out >&1; } | :
因为echo err >&2
不会关心管道的状态。
有时,您会根据是否在有机会运行之前终止而获得err
输出。如果先终止,则由于左侧过早被杀死,将不会有输出。{ echo out >&1; echo err >&2; } | :
:
echo out >&1
:
我猜大多数人不会在大多数系统上经历第二个管道的非确定性行为。尽管如此,您还是发现了显示这一点的操作系统和 shell 版本的组合。我还在 FreeBSD 上复制了非确定性行为zsh
,即使是在单个 shell 会话中(尽管 shell 似乎倾向于一种行为而不是另一种行为,所以我需要 10 次以上的尝试才能最终看到切换)。