tee将其 stdout 发送到 no-op ( :) 命令时,则不会打印任何内容,并且文件大小为零。tee将其标准输出发送到 acat时,所有内容都会正确打印,并且文件大小大于零。这是一个显示它的代码示例(以脚本的第一个输入参数为条件):
#!/usr/bin/env bash
log_filepath="./log.txt"
[ -f "$log_filepath" ] && { rm "$log_filepath" || exit 1 ; }
fail_tee="$1"
while IFS= read -r -d $'\n' line ; do
printf "%s%s\n" "prefix: " "$line" | \
tee -a "$log_filepath" | \
{
if [ -n "$fail_tee" ]; then
# Nothing is printed to stdout/terminal
# $log_filepath size is ZERO.
: # do nothing.
else
# Each line in the input is prefixed w/ "prefix: " and sent to stdout
# $log_filepath size is 46 bytes
cat
fi
}
done <<'EOF'
1
23
456
7890
EOF
Run Code Online (Sandbox Code Playgroud)
希望得到其背后的解释。
我对 no-op:命令的期望是它不应该阻止tee将输出发送到文件。
in仍然:是tee ... |\xc2\xa0:一个进程,持有由 shell 设置的管道的读取端,其另一端正tee在写入。只是:立即退出,这会阻止它从管道中读取数据。(为了使管道同时执行操作,外壳程序必须为管道的每个部分生成一个新进程,即使它只是为了处理 no-op 。:在您的示例中,该进程将运行if语句在管道的最后一部分,然后在“运行”:内置函数后最终退出。)
通常的行为是,当管道的读取器退出(读取端文件描述符关闭)时,写入器在下一次写入时收到 SIGPIPE 信号,这会导致其退出。
\n这通常是您想要的,因为这意味着如果管道的右侧退出,左侧也会退出,并且不会无用地继续可能很长的任务。或者(更糟糕的是)无助地试图写入阻塞的管道,该管道不允许任何写入,因为数据无处可去。
\n因为,POSIX 规范tee中似乎没有任何例外;最接近的部分是提到文件操作数的写入错误:
\n\n如果对任何成功打开的文件操作数的写入失败,则对其他成功打开的文件操作数和标准输出的写入应继续,但退出状态应为非零。
\n
如果 SIGPIPE 被忽略,我测试的实现将继续执行然后从调用EPIPE返回的错误write()。
GNU coreutils 版本tee具有-p和--output-error选项来控制写入失败时执行的操作:
\n\n未指定时的默认操作
\n--output-error是在写入管道时发生错误时立即退出,并诊断写入非管道输出的错误。
虽然它退出的方式是通过 SIGPIPE,所以tee从忽略信号开始,它不会退出。
默认的-p模式warn-nopipe是“诊断写入任何非管道输出的错误”,而不是其他使其退出的选项。在幕后,它还会忽略 SIGPIPE 信号,然后停止尝试写入管道。
因此,至少对于 GNU 版本,您可以使用tee -p ... |\xc2\xa0...它来防止管道读取器退出时退出。或者,您可以将右侧程序安排为模仿黑洞,例如cat > /dev/null(它仍然读取和写入它获得的所有内容,但内核最终会忽略写入的数据/dev/null)。