为什么使用tee重定向并不像预期的那样工作?

时间:2014-05-27 20:57:13

标签: shell io-redirection tee

我想要获得的是将脚本的所有输出记录到文件中,所有这些都在脚本本身中,保存了我在日志文件中看到的所有内容。 如果我没有重定向到文件脚本按预期工作,继续循环直到我按CTRL + C;当发生这种情况时,它会在屏幕上打印几条消息并退出。 如果我尝试使用tee重定向到文件,不仅它不打印消息而且日志不完整,只有循环线,没有任何事情。 这是脚本(缩减版):

#!/bin/sh
EXIT=0
COUNT=0
{
while [ $EXIT -eq 0 ]
do
  COUNT=$((COUNT+1)) && echo "Eternal loop $COUNT" && sleep 1
  trap 'EXIT=1; echo "Loop interrupted by user, exiting."' 15 2 8 20
done
echo "Out of loop, eternity ends"
} | tee log.log 2>&1

我读过并且无法理解我所遇到的问题是由管道发球,stderr和stdout引起的,还是由于我如何使用陷阱引起的。 我是shell脚本的菜鸟,这令人沮丧,任何帮助都将受到赞赏。 感谢。

编辑1: 在阅读了chepner的答案之后,我修改了这样的脚本:

#!/bin/sh
EXIT=0
COUNT=0
rm log.log
while [ $EXIT -eq 0 ]
do
COUNT=$((COUNT+1)) && echo "Eternal loop $COUNT" | tee -a log.log && sleep 1
trap 'EXIT=1; echo "Loop interrupted by user, exiting." | tee -a log.log' 15 2 8 20
done
echo "Out of loop, eternity ends" | tee -a log.log

并且它可以工作,它将输出记录到日志文件中,我仍然可以在屏幕上看到输出,正是我想要的。将不得不在其他脚本上尝试它,但我想它会好起来的。 现在一个问题仍然存在:如果我有很多命令而不仅仅是3,那么这个解决方案是否会干净"足够?我的意思是,我呼唤的那些发球会发生什么?是否有更好的方法来做到这一点,比如更精致?

3 个答案:

答案 0 :(得分:2)

使用管道,前台作业包含两个进程,一个用于管道的每一侧。点击Control-C会将SIGINT发送到所有进程,以便后循环echo无法运行,或者tee输出LHS流程的最终输出。如果没有到tee的管道,while循环完全在当前shell实例中运行,所以shell本身接收SIGINT并且(我相信)只会中断当前的任何shell命令在循环中运行。触发器触发,然后由于EXIT上的条件检查,循环自然退出。

答案 1 :(得分:1)

不完全是您所要求的,但是当您想记录在流程中看到的所有内容时,脚本命令比处理重定向更容易。

如果你想要使用tee,请在管道前面移动重定向

somecommand 2>&1 | tee outfile

答案 2 :(得分:0)

也许您想将stderr重定向到stdout,然后通过管道发送到tee命令:

...
} 2>&1 | tee log.log