为“exec >>(tee -ia $OUT)”创建选项以跳过标准输出

为“exec >>(tee -ia $OUT)”创建选项以跳过标准输出

我试图调整使用以下内容的脚本:

# first portion of script
# ...
exec > >(tee -ia $OUT)
# ...
# second portion of script 

我对这个脚本的问题是它会向stdout(我的终端)产生大量输出。脚本作者没有包含消除终端输出的选项。我想添加一个选项删除stdout, 并仅在文件 中获取输出$OUT

这是我尝试过的:

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else {

# ...
# second portion of script 

} > $OUT
fi

这似乎有效,但我不确定其用途大括号 {}在此背景下作为分组命令的 GNU 部分(好像) 说明;列表后面需要有分号。但添加;或删除似乎没有什么区别。我想知道是否应该使用括号()而不是花括号,但这会导致 中的所有内容都()在子 shell 中执行。我对此不是特别热衷,因为这是别人的剧本&子外壳我不清楚其含义(我没有尝试过)。

我尝试过的另一件事看起来像一个黑客,但我读到其他人使用它,它似乎也工作正常:

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else
     exec > >(tee -ia $OUT 1> /dev/null)
fi

# ...
# second portion of script 

我喜欢这个,因为它看起来更独立的,但这并不是一个值得考虑的事情。

所以问题是: 这样做的正确方法是什么?我的意思是,正确的方法是什么选择退出exec > >(tee -ia $OUT)?后的终端输出这些解决方案中的一种比另一种更可取——还是我需要做一些完全不同的事情?

答案1

仅有的$OUT在挂起模式下重定向到文件a要容易得多:

case $TERM_OPT in
  (OFF) exec >> "$OUT";;
  (*)   exec > >(tee -ia -- "$OUT")
esac

请注意,shell 不会等待tee退出,因此您可能会发现tee脚本完成后仍在输出某些内容。

$ bash -c 'exec > >(tee -ia -- file); echo A'; echo B; sleep 1
B
A

看看AB之后的输出如何。

要解决这个问题,您可以添加:

if [ "$TERM_OPT" != OFF ]; then
  exec > /dev/null # closes the pipe to tee which should cause tee
                   # to see EOF on input and exit
  wait # waits for all asynchronous tasks including tee
fi

在脚本的末尾或EXIT陷阱中。

另一个选择(也可以在 sh 中使用)是将整个脚本放入一个main函数中并执行以下操作:

#! /bin/sh -
main() {
  # your script here
}
case $TERM_OPT in
  (OFF) main "$@" >> "$OUT";;
  (*)   main "$@" | tee -ia -- "$OUT"
esac

答案2

如果您想重定向 stdout 以附加到文件,并且不在终端上保留输出的副本,只需执行以下操作:

exec >> "$OUT"

的唯一目的tee是将一个流复制为多个流,因此如果您只想将输出放在一个位置,则不需要它。你tee -ia "$OUT" > /dev/null当然也可以工作,但这有点愚蠢:你仍然会复制输出,只是为了丢弃另一个副本。

{}我不确定在这种情况下使用花括号

大括号需要分号或换行符。其实手册上是这么说的:“列表后面需要分号(或换行符)。”括号两者都不需要。

子 shell 的含义是,子 shell 在 shell 的独立副本中运行,子 shell 中的任何更改在其外部都是不可见的。如果脚本在子 shell 结束时结束,那没有多大意义,子 shell 所做的只是启动一个不需要的进程。

我会选择类似的东西

if [ "$TERM_OPT" != "OFF" ]; then
     exec > >(tee -ia -- "$OUT")
else
     exec >> "$OUT"
fi

相关内容