使用tee时重定向输出挂起

And*_*han 6 unix linux bash

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

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

我试图用以下方法结束:

exec >&-
Run Code Online (Sandbox Code Playgroud)

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

Eug*_*sca 5

由于某种原因,使用似乎会tee停止出现提示($PS1),因为shell脚本尚未退出。作为一种解决方法,我通常sleep在致电后稍等片刻tee

#!/bin/bash

exec > >(tee -a mylog)
sleep .1
# my code
Run Code Online (Sandbox Code Playgroud)


Jon*_*ler 5

将评论转换为答案,稍作修改。

注意到

以下代码在 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
Run Code Online (Sandbox Code Playgroud)

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

查特拉德 观察到

如果您从示例中删除 sleep 和 date 调用,则脚本将不再正确退出,正如 Andrew 所说:

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
Run Code Online (Sandbox Code Playgroud)

我回应说:

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

我试验了一下:

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

我的印象是 Andrew 在 Bash 中发现了一个可以切实报告的错误。(有关如何执行此操作,请参阅有关报告错误的 Bash 手册。)我认为不会因为 I/O 重定向正常后没有执行任何外部命令而不退出。我可以确认Apple的Bash 3.2.57有问题;这样做的Bash 4.3.27(这是我为自己建造所以它与修复的补丁弹震错误)。

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

它还证实了chatraed解决方法有效,尽管速度比最低限度要慢。对于生产用途,我会选择sleep 0,它比 快十分之一秒sleep 0.1。几分之一秒的睡眠仅适用于某些系统;经典地(根据 POSIX),sleep不会在几秒钟内休眠。OTOH,如果你写sleep 0.1, 在不支持小数秒的系统上,包括前导0可能使它休眠零秒;写作.1可能会也可能不会产生相同的效果。