tee无法退出,执行顺序奇怪

时间:2018-10-16 13:57:01

标签: bash tee

将函数的输出传递到tee命令时,我得到一些奇怪的行为。第一个问题是,在通过管道传输到exit的函数中调用tee命令时,我无法退出程序。例如:

myfunction(){
    # Some stuff here
    exit 1
}

myfunction | tee -a $UPGRADE_LOG

当我运行上面的代码时,程序无法退出并运行完成。

我遇到的另一个问题是tee似乎导致某些代码以取消顺序顺序的方式运行。我有以下输出:

SHOWING SYSTEM-WIDE AND INSTATNCE MEMORY USAGE:
Are you sure you would like to back up the instance given current memory contraints? [y/n]: Filesystem                           Size   Used  Avail  Use%  Mounted on
/dev/mapper/system-root              15G    13G   1.5G   90%   /
Log File Size: 24K   Total Size to Package: 248K Available Space: 1.5G

何时应以以下方式运行:

SHOWING SYSTEM-WIDE AND INSTATNCE MEMORY USAGE:
Filesystem                           Size   Used  Avail  Use%  Mounted on
/dev/mapper/system-root              15G    13G   1.5G   90%   /
Log File Size: 24K   Total Size to Package: 248K Available Space: 1.5G
Are you sure you would like to back up the instance given current memory contraints? [y/n]: 

不使用tee时,一切正常。这些问题似乎彼此相关。有什么想法为什么会这样,我该怎么办?

2 个答案:

答案 0 :(得分:2)

kvantour's answer告诉您为什么会发生这种情况。这个告诉您如何解决它。 :)

with_logs_piped() {
  local logfile=$1; shift
  "$@" > >(tee -a -- "$logfile") 2>&1  # 2>&1 redirects stderr through the same tee so it's
}                                      # ...also logged, and shows up sync'd with stdout.

myfunction() {
    # Some stuff here
    exit 1
}

with_logs_piped "$UPGRADE_LOG" myfunction

这里重要的是,我们使用process substitution代替tee来使用常规管道,因此myfunction在您的shell本身而不是子shell中运行,因此exit正确适用。


关于通过tee重定向stdout会使stderr不同步的原因,请参见Separately redirecting and recombining stderr/stdout without losing ordering

答案 1 :(得分:1)

exit语句退出进程正在运行的(子)shell。现在出现了惊喜:

  

管道

     

管道是一系列由一个或多个控制操作符||&分隔的命令。管道的格式为:

[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]
     

     

管道中的每个命令都作为单独的进程(即在子外壳中)执行。

     

来源:man bash

因此,该函数中的exit语句只是杀死了管道的子外壳。这实际上意味着exit在管道中什么也不做

$ exit | exit | echo foo
foo
$ exit | exit
$ # shell not terminated

注意:这显然取决于外壳,因为的行为有所不同。