【问题标题】:tee hangs in bash -- is there an alternative syntax?tee 挂在 bash 中——是否有替代语法?
【发布时间】:2018-11-16 03:38:18
【问题描述】:

假设您有一系列不属于您的脚本,因此无法修改,它们可能会在不重定向 stdout 和 stderr 的情况下生成后台进程。我注意到,在 bash 中,如下例所示,如果后台进程仍在运行(并且为 stdout 或 stderr 打开了文件描述符),则在脚本完成时不会返回输出。

./runme.sh 2>&1| tee runme.out

其中runme.sh定义为:

#!/bin/bash
# Start a fake daemon
perl -e 'while(1) { sleep(1) }' &
printf "Enter your name: "
read name
echo "Goodbye $name"

如何在 bash 中运行这样的脚本,同时捕获所有输出并在脚本完成后返回提示符?

【问题讨论】:

    标签: bash daemon tee


    【解决方案1】:

    替代语法可以是使用进程替换

    ./runme.sh > >(tee runme.out) 2>&1
    

    这样tee 不再是当前shell 的子进程,shell 将只等待runme.sh 终止,而在管道中它正在等待所有进程终止。

    注意tee 和子进程在runme.sh 终止后仍在运行。

    【讨论】:

      【解决方案2】:

      如果后台进程仍在运行(并且具有用于 stdout 或 stderr 的打开文件描述符),则不会在脚本完成时返回

      所以不要那样做。出于这个原因,守护程序工具通常会重定向 stdout/err,您也可以手动进行:

      perl -e 'while(1) { sleep(1) }' < /dev/null  > mydaemon.log 2>&1 &
      

      现在它没有保持管道打开,您可以tee 健壮而无需黑客攻击。

      【讨论】: