创建输出到多个目标的文件描述符

Create file descriptor which outputs to multiple targets

我正在写一个脚本,它的大部分输出最好发送到日志文件,但我想 'opt in' 某些命令到控制台输出,例如显式脚本 status/feedback 条消息。

我创建了三个命名文件描述符:一个用于终端,一个用于日志,还有一个同时用于终端和日志。我曾尝试使用 tee 将输入发送到 $both 并使其到达 $term$log,但这似乎具有重新排序输出的效果。有没有办法实现上述但保留输出顺序?

# Create FD 'term' with target == stdout's current target
exec {term}>&1

# Create FD 'log' with target == ./my-log.txt
exec {log}>"$log_path"

# Attempt to use tee to split output off into $log FD and send stdout to $term FD
exec {both}> >(tee -a "/dev/fd/$log" 1>&$term)

# Set stdout and stderr to route to $log FD
exec 1>&$log 2>&$log

            echo 1 - example output of command
1>&$both    echo 2 - script feedback/status
            echo 3 - example output of command
1>&$both    echo 4 - script feedback/status
            echo 5 - example output of command

# stdout:
#   2 - script feedback/status
#   4 - script feedback/status

# $log_path:
#   1 - example output of command
#   3 - example output of command
#   5 - example output of command
#   2 - script feedback/status
#   4 - script feedback/status

谢谢

问题是,当您将输出发送到 both 时,bash 不会等到 tee 实际写出它才移到下一行,所以您以 bashtee 的竞争条件结束,对 log 进行不同步写入。除非你有充分的理由需要一个 FD,否则最简单和最好的解决方案可能就是这样做:

exec {term}>&1 >"$log_path" 2>&1
echo 1 - example output of command
echo 2 - script feedback/status | tee "/dev/fd/$term"
echo 3 - example output of command
echo 4 - script feedback/status | tee "/dev/fd/$term"
echo 5 - example output of command

根据另一个答案,你可以进一步定义echo2函数:

echo2(){
    echo "$@" | tee "/dev/fd/$term"
}

exec {term}>&1 >"$log_path" 2>&1

echo  1 - example output of command
echo2 2 - script feedback/status
echo  3 - example output of command
echo2 4 - script feedback/status
echo  5 - example output of command