在 bash 中,如何从由 tee 传输的函数中退出脚本?

In bash how do I exit a script from a function that is piped by tee?

我试图理解为什么每当我使用 function 2>&1 | tee -a $LOG tee 时都会在函数中创建一个无法通过简单 exit 1 退出的子外壳(如果我不使用 tee 它工作正常)。下面的例子:

#!/bin/bash
LOG=/root/log.log

function first()
{
echo "Function 1 - I WANT to see this."
exit 1
}

function second()
{
echo "Function 2 - I DON'T WANT to see this."
exit 1
}
first 2>&1 | tee -a $LOG
second 2>&1 | tee -a $LOG

输出:

[root@linuxbox ~]# ./1.sh  
Function 1 - I WANT to see this.
Function 2 - I DON'T WANT to see this.

所以。如果我删除 | tee -a $LOG 部分,它将按预期工作(脚本将在第一个函数中退出)。

能否请您解释一下如何克服这个问题并在函数中正确退出,同时能够输出 tee?

如果你创建一个管道,函数是 运行 在子shell,如果你 exit 来自子shell,只有子shell 会受到影响,而不是父级 shell。

printPid(){ echo $BASHPID; }

printPid #some value
printPid #same value
printPid | tee #an implicit subshell -- different value
( printPid ) #an explicit subshell -- also a different value

如果您不选择 aFunction | tee

aFunction > >(tee)

基本相同,除了 aFunction 不会 运行 在子 shell 中,因此将能够影响当前环境(设置变量,调用退出等)。

如果管道中的任何内容失败,您可以告诉 bash 失败 set -e -o pipefail:

$ cat test.sh
#!/bin/bash
LOG=~/log.log

set -e -o pipefail

function first()
{
echo "Function 1 - I WANT to see this."
exit 1
}

function second()
{
echo "Function 2 - I DON'T WANT to see this."
exit 1
}
first 2>&1 | tee -a $LOG
second 2>&1 | tee -a $LOG
$ ./test.sh
Function 1 - I WANT to see this.

使用PIPESTATUS检索管道中第一个命令的退出状态。

first 2>&1 | tee -a $LOG; test ${PIPESTATUS[0]} -eq 0 || exit ${PIPESTATUS[0]}
second 2>&1 | tee -a $LOG; test ${PIPESTATUS[0]} -eq 0 || exit ${PIPESTATUS[0]}