我可以在 shell 脚本中暂时停止 'tee' 吗?

Can I stop 'tee' temporarily in a shell script?

bash 4.2 centos7


test.sh

LOG_FILE=./logs/result.log

exec > >(tee -a ${LOG_FILE} )
exec 2> >(tee -a ${LOG_FILE} >&2)
echo

for x in {1..3}
do
  echo $x
done


# I want the second part to be displayed but not logged.
for x in {4..6}
do
  echo $x
done


# Recommence logging
for x in {7..9}
do
  echo $x
done

期望输出

控制台

1
2
3
4
5
6
7
8
9

result.log

1
2
3
7
8
9

问题

我可以在同一个 shell 中停止或恢复 exec > >(tee -a ${LOG_FILE} ) 的重定向吗?
或者我应该使用不同于 tee 的方法?


编辑2

我正在努力从日志中删除此功能。

spinner()
{
  trap "kill 0" SIGINT
  spin='-\|/'
  i=0
  while kill -0  2>/dev/null
  do
    i=$(( (i+1) %4 ))
    printf "\e[1;33m" >&3
    printf "\r${spin:$i:1}" >&3
    printf "\e[m" >&3
    sleep .1
  done
}

我将 >&3 放在三行 printf 中,但结果是 Bad file descriptor。该函数获取一个 pid 参数并旋转轮子,直到完成传递的 pid。

您需要保存原始标准输出的副本,以便您可以再次将中间部分发送给它,如下所示:

#!/bin/bash

LOG_DIR="./logs"
LOG_FILE="$LOG_DIR/result.log"

mkdir -p "$LOG_DIR"

exec 3>&1   # Save a copy of standard output as file descriptor 3

exec > >(tee -a ${LOG_FILE} )
exec 2> >(tee -a ${LOG_FILE} >&2)
echo

for x in {1..3}
do
  echo $x
done

# I want the second part to be displayed but not logged.
{
for x in {4..6}
do
  echo $x
done
} 1>&3

# Recommence logging
for x in {7..9}
do
  echo $x
done

有多种方法可以恢复中间部分以仅写入原始标准输出,但我认为 { … } 1>&3 表示法可能是最简单的。

注意:您有两个 tee 副本都写入同一个文件。如果你幸运(小心),一个处理标准错误将不会有任何东西写入日志文件。您最好像这样使用 2>&1 exec > >(tee …) 2>&1 并省略 exec 2> >(tee …) 行。另请注意,提示可能会出现在最后一个日志输出之前。

$ bash script.sh
4
5
6
$
1
2
3
7
8
9
echo Hi
Hi
$

我在 6 之后的行中输入 echo Hi 到提示符 $

我每次测试脚本时,文件 logs/result.log 都包含一份序列“空行,数字 1-3,数字 7-9”。

另请参阅 Bash 手册: