6

我有一个大的 bash 脚本,我想将所有 stdout/stderr 全局重定向到一个文件,除了一些进度指示器,比如特定的回显消息。例如,考虑以下脚本

#!/bin/bash

# all stdout and stderr go to out.log
exec &> out.log

special_echo "starting"

# many other commands go here
# which output both the stdout and stderr
# also some special_echo commands in here,
# for example
echo "msg1"
special_echo "middle"
echo "msg2" >&2

special_echo "finished"

当它运行时,输出应该是

$ ./script
starting
middle
finished
$

但是,out.log应该包含

msg1
msg2

如何实现special_echo功能?我尝试使用文件描述符并对其进行回显,但无法将其显示在屏幕上。

有没有一种方法可以在不将重定向附加到每一行或在此答案中执行类似操作的情况下实现此目的?

4

3 回答 3

11

是的,使用另一个文件描述符是要走的路:

#!/bin/bash

exec 3>&1
special_echo () {
    echo "$@" >&3
}

exec &> out.log

special_echo "starting"
echo "msg1"
special_echo "middle"
echo "msg2" >&2
special_echo "finished"
于 2013-08-07T10:43:34.757 回答
1

重定向到 /dev/tty,这是控制终端。也适用于输入。

于 2013-08-07T10:49:51.977 回答
0

在脚本开始时,将stdout&保存stderr为自定义描述符。

# all stdout and stderr go to out.log
exec 3>&1 4>&2 &>out.log

您可以使用3>/dev/stdout而不是3>&1等等,或者将其拆分为多个exec重定向行,如果这对您来说更具可读性。

然后你需要做的就是使用它们

echo "starting" >&3
echo "msg1"
echo "middle"   >&3
echo "msg2" >&2
echo "finished" >&3

你不能使用>/dev/stdout,因为它实际上被覆盖了exec,自定义描述符是必要的。

最好的部分是您仍然可以访问原始stderr文件,而您不会使用它。/dev/tty

echo "special error" >&4

如果您需要,您可以完全撤消脚本其余部分的重定向。

#restore original
exec >&3 2>&4

echo "this is special now"

没有函数,没有变量,只是工作。

于 2018-12-17T00:44:37.573 回答