使用exec和写入屏幕的Bash脚本全局重定向

时间:2013-08-07 10:38:09

标签: bash

我有一个大的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功能?我已经尝试过使用文件描述符并回显,但无法将其显示在屏幕上。

有没有办法实现这一目标,而无需将重定向添加到每一行或执行此类answer之类的操作?

3 个答案:

答案 0 :(得分:7)

是的,使用另一个文件描述符是可行的方法:

#!/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"

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

# 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"

没有功能,没有变量,就可以了。

相关问题