如果我将输出通过管道传输到 tee,则无法“继续”
Posted
技术标签:
【中文标题】如果我将输出通过管道传输到 tee,则无法“继续”【英文标题】:Can't "continue" if I pipe output to tee 【发布时间】:2020-02-05 00:39:35 【问题描述】:我有一个 bash 脚本,它使用以下结构几乎可以完成我想要的工作:
for x in 1 2 3
do
[[ $x -ne 2 ]] || continue
echo $x
&>> foo.log
done
我需要对其进行更改,以便将输出同时发送到终端和日志文件。但是,这不起作用:
for x in 1 2 3
do
[[ $x -ne 2 ]] || continue
echo $x
2>&1 | tee -a foo.log
done
看起来,通过创建一个进程,管道阻止我使用continue
。
当然,我可以在没有continue
的情况下重写我的脚本逻辑,但在我开始之前,我想知道我是否错过了一种更直接的方法来实现我想要的。
【问题讨论】:
管道中的命令在子进程中运行;子进程不能更改父 shell 进程中的控制流(或更改变量,或...)。因此,continue
、break
、exit
等在管道中无法完全发挥作用。
这就是为什么我说:“通过创建一个流程”。我的问题不是“为什么在这里继续被拒绝”。
【参考方案1】:
您可以将输出重定向到进程替换。
for x in 1 2 3
do
[[ $x -ne 2 ]] || continue
echo $x
2>&1 > >(tee -a foo.log)
done |
# I suggest to do pipe the output to ex. `cat`, so that the output
# of process substitution will be synchronized with rest of the script
cat
但是为什么不直接重定向整个循环的输出呢?
for x in 1 2 3; do
[[ $x -ne 2 ]] || continue
echo $x
done 2>&1 | tee -a foo.log
您可以退出子进程。如果你愿意这样做,我建议将
替换为
(
)
只是为了安全起见,如果你有一天决定删除 tee
。
for x in 1 2 3
do
[[ $x -ne 2 ]] || exit
echo $x
2>&1 | tee -a foo.log
done
【讨论】:
我无法重定向整个循环(其中有一个 cd,因此输出实际上被发送到单独的日志文件)。我喜欢“过程替代”的想法。这是我不熟悉的语法。但是,我不明白“将输出通过管道传输到...”的评论。 “退出”方法有点吓人,但可能是最简单的(有一个大注释要记住不要移除管道)。感谢您的建议。 比较echo 1 > >(sleep 1; tee something)
和echo 1 > >(sleep 1; tee something) | cat
的输出。问题是>(part)
在后台运行,所以如果它比脚本的其余部分慢,它的输出将与其他命令异步运行。所以echo 1 > >(tee something); echo 2
可能会导致先打印2
,然后再打印1
。要同步它,请使用管道。 Pipe 确保进程替换在运行下一个命令之前结束。
但是“| cat”重新引入了我要解决的“继续”问题! ;-) 我可能会走“退出”路线...以上是关于如果我将输出通过管道传输到 tee,则无法“继续”的主要内容,如果未能解决你的问题,请参考以下文章