使用tee

时间:2015-06-06 20:59:09

标签: linux bash unix

我想在bash脚本中提供可选的日志记录参数,并希望从一开始就使用exectee管道。但是,打开tee进程导致脚本挂起,我相信因为stdout没有关闭:

# Output to a log file, if set
if [[ $OPT_LOG ]]; then
    exec > >(tee -a $OPT_LOG)
fi

我试图结束:

exec >&-

但它仍然挂起 - 有没有另一种正确关闭tee的方法,以便脚本在执行结束时正确退出?

2 个答案:

答案 0 :(得分:4)

由于某些原因,使用tee似乎会停止显示提示符($PS1),因为shell脚本尚未退出。作为解决方法,我通常在调用sleep后使用短tee

#!/bin/bash

exec > >(tee -a mylog)
sleep .1
# my code

答案 1 :(得分:3)

将评论转换为答案,并进行少量修改。

noted

  

以下代码在Mac OS X 10.10.3上为我退出。

OPT_LOG=file.name
if [[ $OPT_LOG ]]
then exec > >(tee -a $OPT_LOG)
fi
for ((i = 0; i < 10; i++))
do
    echo "Logging message $i at $(date)"
    sleep 1
done
     

您的问题可能在您未显示的代码中。你在运行什么命令?你从bash -x yourscript.sh获得了什么?

chatraed observed

  

如果您从示例中删除了睡眠和日期调用,则安德鲁告诉该脚本不再正常退出:

OPT_LOG=file.name;
if [[ $OPT_LOG ]]; then exec > >(tee -a $OPT_LOG); fi;
for ((i = 0; i < 10; i++)); do echo "Logging message $i"; done

我回答说:

  

现在这是一个有趣的观察!我可以重现你的结果。

我试验了一下:

  • 我在for循环之前添加了一个pwd,只是'只有回声',这不会影响事情(但pwd可能是内置的Bash)。
  • 我添加了bash -c 'exit 0'(不是内置的),代码终止了。
  • 我尝试在屏幕上或文件中使用> >(tee -a $OPT_LOG &)并且输出没有出现。 (我觉得这很令人惊讶,但这是一次尝试的解决方法,而不是工作的主要部分。)

我的印象是安德鲁在Bash中发现了一个可以被报道的错误。 (有关如何执行此操作,请参阅Reporting Bugs上的Bash手册。)我认为不会因为I / O重定向没有执行外部命令而退出。我可以确认Apple的Bash 3.2.57有问题; Bash 4.3.27也是如此(我为自己构建的,所以它修补了ShellShock bug的修复程序。)

shell脚本不会调用任何外部命令,并且在exec重定向之后调用任何外部命令似乎可以抑制该错误,这是相对不寻常的。

它还确认chatraedworkaround有效,尽管速度比最低限度要慢。对于生产用途,我选择sleep 0,其速度比sleep 0.1快十分之一秒。只有一秒钟的睡眠只适用于某些系统;经典地(并且根据POSIX),sleep不会在小数秒内睡眠。 OTOH,如果你在不支持小数秒的系统上编写sleep 0.1,包括领先的0,可能会让它在零秒内休眠;写.1可能会或可能不会产生相同的效果。