我可以在 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 手册:
- I/O Redirection
- Duplicating file descriptors
- Command grouping 以获得
{ … }
. 的解释
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 手册:
- I/O Redirection
- Duplicating file descriptors
- Command grouping 以获得
{ … }
. 的解释