将函数的输出传递到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
时,一切正常。这些问题似乎彼此相关。有什么想法为什么会这样,我该怎么办?
答案 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
注意:这显然取决于外壳,因为zsh的行为有所不同。